/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ // // � Microsoft Corporation. All rights reserved. // using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Globalization; using System.Reflection; using System.Linq.Expressions; using System.Linq; using System.Diagnostics; using Microsoft.Research.DryadLinq.Internal; using Microsoft.Research.Dryad.Hdfs; namespace Microsoft.Research.DryadLinq { // This class introduces some new operators into the expression tree. So far, // there are two classes of new operators: // 1. HashPartition, RangePartition, Merge // 2. Apply public static class HpcLinqQueryable { internal static bool IsLocalDebugSource(IQueryable source) { return !(source.Provider is DryadLinqProvider); } public static IQueryable LongWhere(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongWhere(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable LongSelect(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongSelect(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable LongSelectMany(this IQueryable source, Expression>> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongSelectMany(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable LongSelectMany(this IQueryable source, Expression>> selector, Expression> resultSelector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (resultSelector == null) { throw new ArgumentNullException("resultSelector"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongSelectMany(source, selector.Compile(), resultSelector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TCollection), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector), Expression.Quote(resultSelector) } )); } public static IQueryable LongTakeWhile(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongTakeWhile(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable LongSkipWhile(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var result = HpcLinqEnumerable.LongSkipWhile(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, result); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } /// /// Hash partition a dataset. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The function to extract the key from a record /// An EqualityComparer on TKey to compare keys /// The number of partitions to create /// An IQueryable partitioned according to a key public static IQueryable HashPartition(this IQueryable source, Expression> keySelector, IEqualityComparer comparer, int partitionCount) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IEqualityComparer)), Expression.Constant(partitionCount, typeof(int)) } )); } /// /// Hash partition a dataset. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// the dataset to be partitioned /// The funtion to extract the key from a record /// The number of partitioned to create /// An IQueryable partitioned according to a key public static IQueryable HashPartition(this IQueryable source, Expression> keySelector, int partitionCount) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(partitionCount, typeof(int)) } )); } /// /// Hash partition a dataset. The number of resulting partitions is dynamically determined /// at the runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// the dataset to be partitioned /// The function to extract the key from a record /// An IQueryable partitioned according to a key public static IQueryable HashPartition(this IQueryable source, Expression> keySelector) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector) } )); } /// /// Hash partition a dataset. The number of resulting partitions is dynamically determined /// at the runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The function to extract the key from a record /// An IComparer on TKey to compare keys /// An IQueryable partitioned according to a key public static IQueryable HashPartition(this IQueryable source, Expression> keySelector, IEqualityComparer comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IEqualityComparer)) } )); } /// /// Range partition a dataset. The list of range keys are determined dynamically at /// runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The function to extract the key from a record /// An IQueryable partitioned according to a key public static IQueryable RangePartition(this IQueryable source, Expression> keySelector) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector) } )); } /// /// Range partition a dataset. The list of range keys are determined dynamically at /// runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The function to extract the key from a record /// Number of partitions in the output dataset /// An IQueryable partitioned according to a key public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, int partitionCount) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(partitionCount, typeof(int)) } )); } /// /// Range partition a dataset. The list of range keys are determined dynamically at /// runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The funtion to extract the key from a record /// true if the partition keys are descending /// An IQueryable partitioned according to a key public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(isDescending, typeof(bool)) } )); } public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, TKey[] rangeSeparators) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (rangeSeparators == null) throw new ArgumentNullException("rangeSeparators"); // check that the range-keys are consistent. bool? dummy; if (!HpcLinqUtil.ComputeIsDescending(rangeSeparators, Comparer.Default, out dummy)) { throw new ArgumentException(SR.PartitionKeysAreNotConsistentlyOrdered, "rangeSeparators"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(rangeSeparators, typeof(TKey[])) } )); } /// /// Range partition a dataset. The list of range keys are determined dynamically at /// runtime. /// /// The type of the records in the dataset /// The type of the key on which the partition is based /// The dataset to be partitioned /// The funtion to extract the key from a record /// true if the partition keys are descending /// Number of partitions in the output dataset /// An IQueryable partitioned according to a key public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, bool isDescending, int partitionCount ) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(isDescending, typeof(bool)), Expression.Constant(partitionCount, typeof(int)) } )); } public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, IComparer comparer, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)), Expression.Constant(isDescending, typeof(bool)) } )); } public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, TKey[] rangeSeparators, IComparer comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (rangeSeparators == null) throw new ArgumentNullException("rangeSeparators"); if (comparer == null && !TypeSystem.HasDefaultComparer(typeof(TKey))) { throw new DryadLinqException(HpcLinqErrorCode.ComparerMustBeSpecifiedOrKeyTypeMustBeIComparable, string.Format(SR.ComparerMustBeSpecifiedOrKeyTypeMustBeIComparable, typeof(TKey))); } comparer = TypeSystem.GetComparer(comparer); // check that the range-keys are consistent. bool? dummy; if (!HpcLinqUtil.ComputeIsDescending(rangeSeparators, comparer, out dummy)) { throw new ArgumentException(SR.PartitionKeysAreNotConsistentlyOrdered, "rangeSeparators"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(rangeSeparators, typeof(TKey[])), Expression.Constant(comparer, typeof(IComparer)) } )); } public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, IComparer comparer, bool isDescending, int partitionCount) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (partitionCount <= 0) { throw new ArgumentOutOfRangeException("partitionCount"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)), Expression.Constant(isDescending, typeof(bool)), Expression.Constant(partitionCount, typeof(int))} )); } public static IQueryable RangePartition(this IQueryable source, Expression> keySelector, TKey[] rangeSeparators, IComparer comparer, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (rangeSeparators == null) throw new ArgumentNullException("rangeSeparators"); if (comparer == null && !TypeSystem.HasDefaultComparer(typeof(TKey))) { throw new DryadLinqException(HpcLinqErrorCode.ComparerMustBeSpecifiedOrKeyTypeMustBeIComparable, string.Format(SR.ComparerMustBeSpecifiedOrKeyTypeMustBeIComparable, typeof(TKey))); } comparer = TypeSystem.GetComparer(comparer); // check that the range-keys are consistent. bool? detectedDescending; bool keysAreConsistent = HpcLinqUtil.ComputeIsDescending(rangeSeparators, comparer, out detectedDescending); // Note: detectedDescending==null implies that we couldn't precisely tell (single element, repeated elements, etc). if (!keysAreConsistent) { throw new ArgumentException(SR.PartitionKeysAreNotConsistentlyOrdered, "rangeSeparators"); } // and check that the actual direction of keys matches what the user said they wanted. if (detectedDescending != null && detectedDescending != isDescending) { throw new ArgumentException(SR.IsDescendingIsInconsistent); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(rangeSeparators, typeof(TKey[])), Expression.Constant(comparer, typeof(IComparer)), Expression.Constant(isDescending, typeof(bool)) } )); } /// /// Compute applyFunc (source) /// /// The type of the records of the input dataset /// The type of the records of the output dataset /// The input dataset /// The function to be applied to the input dataset /// The result of computing applyFunc(source) public static IQueryable Apply(this IQueryable source, Expression, IEnumerable>> applyFunc) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = applyFunc.Compile()(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.Quote(applyFunc) } )); } /// /// Compute applyFunc(source1, source2) /// /// The type of the records of the first input dataset /// The type of the records of the second input dataset /// he type of the records of the output dataset /// The first input dataset /// The second input dataset /// The function to be applied to the input datasets /// The result of computing applyFunc(source1, source2) public static IQueryable Apply(this IQueryable source1, IQueryable source2, Expression, IEnumerable, IEnumerable>> applyFunc) { if (source1 == null) { throw new ArgumentNullException("source1"); } if (source2 == null) { throw new ArgumentNullException("source2"); } if (IsLocalDebugSource(source1)) { var q = applyFunc.Compile()(source1, source2).AsQueryable(); return new DryadLinqLocalQuery(source1.Provider, q); } return source1.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2), typeof(T3)), new Expression[] { source1.Expression, source2.Expression, Expression.Quote(applyFunc) } )); } /// /// Compute applyFunc on multiple sources /// /// The type of the records of input /// The type of the records of output /// The first input dataset /// Other input datasets /// The function to be applied to the input datasets /// The result of computing applyFunc(source,pieces) public static IQueryable Apply(this IQueryable source, IQueryable[] otherSources, Expression[], IEnumerable>> applyFunc) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IQueryable[] allSources = new IQueryable[otherSources.Length + 1]; allSources[0] = source; for (int i = 0; i < otherSources.Length; ++i) { allSources[i + 1] = otherSources[i]; } var q = applyFunc.Compile()(allSources).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } Expression[] others = new Expression[otherSources.Length]; for (int i = 0; i < otherSources.Length; i++) { others[i] = otherSources[i].Expression; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.NewArrayInit(typeof(IQueryable), others), Expression.Quote(applyFunc) } )); } /// /// Compute applyFunc (source) /// /// The type of the records of the input dataset /// The type of the records of the output dataset /// The input dataset /// The function to be applied to the input dataset /// The result of computing applyFunc(source) public static IQueryable ApplyPerPartition( this IQueryable source, Expression, IEnumerable>> applyFunc) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = applyFunc.Compile()(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.Quote(applyFunc) } )); } /// /// Compute applyFunc(source1, source2) /// /// The type of the records of the first input dataset /// The type of the records of the second input dataset /// he type of the records of the output dataset /// The first input dataset /// The second input dataset /// The function to be applied to the input datasets /// True if only distributive over the first dataset /// The result of computing applyFunc(source1, source2) public static IQueryable ApplyPerPartition( this IQueryable source1, IQueryable source2, Expression, IEnumerable, IEnumerable>> applyFunc, bool isFirstOnly) { if (source1 == null) { throw new ArgumentNullException("source1"); } if (source2 == null) { throw new ArgumentNullException("source2"); } if (IsLocalDebugSource(source1)) { var q = applyFunc.Compile()(source1, source2).AsQueryable(); return new DryadLinqLocalQuery(source1.Provider, q); } return source1.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2), typeof(T3)), new Expression[] { source1.Expression, source2.Expression, Expression.Quote(applyFunc), Expression.Constant(isFirstOnly) } )); } /// /// Compute applyFunc on multiple sources /// /// The type of the records of input /// The type of the records of output /// The first input dataset /// Other input datasets /// The function to be applied to the input datasets /// True if only distributive over the first dataset /// The result of computing applyFunc(source,pieces) public static IQueryable ApplyPerPartition( this IQueryable source, IQueryable[] otherSources, Expression[], IEnumerable>> applyFunc, bool isFirstOnly) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IQueryable[] allSources = new IQueryable[otherSources.Length + 1]; allSources[0] = source; for (int i = 0; i < otherSources.Length; ++i) { allSources[i + 1] = otherSources[i]; } var q = applyFunc.Compile()(allSources).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } Expression[] others = new Expression[otherSources.Length]; for (int i = 0; i < otherSources.Length; i++) { others[i] = otherSources[i].Expression; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.NewArrayInit(typeof(IQueryable), others), Expression.Quote(applyFunc), Expression.Constant(isFirstOnly) } )); } /// /// Apply a function on every sliding window on the input sequence of records. /// /// The type of the input records /// The type of the output records /// The input dataset /// The function to apply to every sliding window /// The size of the window /// public static IQueryable SlidingWindow(this IQueryable source, Expression, T2>> procFunc, Int32 windowSize) { if (source == null) { throw new ArgumentNullException("source"); } if (windowSize < 2) { throw new DryadLinqException(SR.WindowSizeMustyBeGTOne); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SlidingWindow(source, procFunc.Compile(), windowSize); return new DryadLinqLocalQuery(source.Provider, q.AsQueryable()); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.Quote(procFunc), Expression.Constant(windowSize, typeof(int))} )); } public static IQueryable SelectWithPartitionIndex(this IQueryable source, Expression> procFunc) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SelectWithPartitionIndex(source, procFunc.Compile()); return new DryadLinqLocalQuery(source.Provider, q.AsQueryable()); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.Quote(procFunc) } )); } public static IQueryable ApplyWithPartitionIndex(this IQueryable source, Expression, int, IEnumerable>> procFunc) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = procFunc.Compile()(source, 0); return new DryadLinqLocalQuery(source.Provider, q.AsQueryable()); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T1), typeof(T2)), new Expression[] { source.Expression, Expression.Quote(procFunc) } )); } public static IQueryable AnyAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AnyAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable AnyAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AnyAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable AllAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AllAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable CountAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.CountAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable CountAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.CountAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable LongCountAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.LongCountAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable LongCountAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.LongCountAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable ContainsAsQuery(this IQueryable source, TSource item) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.ContainsAsQuery(source, item).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Constant(item, typeof(TSource)) } )); } public static IQueryable ContainsAsQuery(this IQueryable source, TSource item, IEqualityComparer comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.ContainsAsQuery(source, item, comparer).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Constant(item, typeof(TSource)), Expression.Constant(comparer, typeof(IEqualityComparer)) } )); } private static Expression GetSourceExpression(IEnumerable source) { IQueryable q = source as IQueryable; if (q != null) return q.Expression; return Expression.Constant(source.ToArray(), typeof(TSource[])); } public static IQueryable SequenceEqualAsQuery(this IQueryable source1, IEnumerable source2) { if (source1 == null) { throw new ArgumentNullException("source1"); } if (source2 == null) { throw new ArgumentNullException("source2"); } if (IsLocalDebugSource(source1)) { var q = HpcLinqEnumerable.SequenceEqualAsQuery(source1, source2).AsQueryable(); return new DryadLinqLocalQuery(source1.Provider, q); } return source1.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source1.Expression, GetSourceExpression(source2) } )); } public static IQueryable SequenceEqualAsQuery(this IQueryable source1, IEnumerable source2, IEqualityComparer comparer) { if (source1 == null) { throw new ArgumentNullException("source1"); } if (source2 == null) { throw new ArgumentNullException("source2"); } if (IsLocalDebugSource(source1)) { var q = HpcLinqEnumerable.SequenceEqualAsQuery(source1, source2, comparer).AsQueryable(); return new DryadLinqLocalQuery(source1.Provider, q); } return source1.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source1.Expression, GetSourceExpression(source2), Expression.Constant(comparer, typeof(IEqualityComparer)) } )); } public static IQueryable FirstAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.FirstAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable FirstAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.FirstAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable LastAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.LastAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable LastAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.LastAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable SingleAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SingleAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable SingleAsQuery(this IQueryable source, Expression> predicate) { if (source == null) { throw new ArgumentNullException("source"); } if (predicate == null) { throw new ArgumentNullException("predicate"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SingleAsQuery(source, predicate.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(predicate) } )); } public static IQueryable MinAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.MinAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable MinAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.MinAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable MaxAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.MaxAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression } )); } public static IQueryable MaxAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.MaxAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable SumAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.SumAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()), new Expression[] { source.Expression } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AverageAsQuery(this IQueryable source, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AverageAsQuery(source, selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(selector) } )); } public static IQueryable AggregateAsQuery(this IQueryable source, Expression> func) { if (source == null) { throw new ArgumentNullException("source"); } if (func == null) { throw new ArgumentNullException("func"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AggregateAsQuery(source, func.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Quote(func) } )); } public static IQueryable AggregateAsQuery(this IQueryable source, TAccumulate seed, Expression> func) { if (source == null) { throw new ArgumentNullException("source"); } if (func == null) { throw new ArgumentNullException("func"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AggregateAsQuery(source, seed, func.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TAccumulate)), new Expression[] { source.Expression, Expression.Constant(seed), Expression.Quote(func) } )); } public static IQueryable AggregateAsQuery(this IQueryable source, TAccumulate seed, Expression> func, Expression> selector) { if (source == null) { throw new ArgumentNullException("source"); } if (func == null) { throw new ArgumentNullException("func"); } if (selector == null) { throw new ArgumentNullException("selector"); } if (IsLocalDebugSource(source)) { var q = HpcLinqEnumerable.AggregateAsQuery(source, seed, func.Compile(), selector.Compile()).AsQueryable(); return new DryadLinqLocalQuery(source.Provider, q); } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TAccumulate), typeof(TResult)), new Expression[] { source.Expression, Expression.Constant(seed), Expression.Quote(func), Expression.Quote(selector) } )); } /// /// Instruct DryadLINQ to assume that the dataset is hash partitioned. /// /// The type of the records of the dataset /// The type of the keys on which the partition is based /// The dataset /// The function to extract the key from a record /// The same dataset as input public static IQueryable AssumeHashPartition(this IQueryable source, Expression> keySelector) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector) } )); } public static IQueryable AssumeHashPartition(this IQueryable source, Expression> keySelector, IEqualityComparer comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IEqualityComparer)) } )); } /// /// Instruct DryadLINQ to assume that the dataset is range partitioned. /// /// The type of the records of the dataset /// The type of the key on which partition is based /// The dataset /// The function to extract the key from a record /// true if the partition keys are ordered descendingly /// The same dataset as input public static IQueryable AssumeRangePartition(this IQueryable source, Expression> keySelector, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(isDescending) } )); } public static IQueryable AssumeRangePartition(this IQueryable source, Expression> keySelector, IComparer comparer, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)), Expression.Constant(isDescending) } )); } public static IQueryable AssumeRangePartition(this IQueryable source, Expression> keySelector, TKey[] rangeSeparators) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (rangeSeparators == null) { throw new ArgumentNullException("rangeSeparators"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(rangeSeparators) } )); } public static IQueryable AssumeRangePartition(this IQueryable source, Expression> keySelector, TKey[] rangeSeparators, IComparer comparer) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (rangeSeparators == null) { throw new ArgumentNullException("rangeSeparators"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(rangeSeparators), Expression.Constant(comparer, typeof(IComparer)) } )); } /// /// Instruct DryadLINQ to assume that each partition of the dataset is ordered. A dataset /// is ordered if it is range partitioned and each partition of it is ordered on the same /// key. /// /// The type of the recrods of the dataset /// The type of the key on which partition is based /// The dataset /// The function to extract the key from a record /// true if the order is descending /// The same dataset as input public static IQueryable AssumeOrderBy(this IQueryable source, Expression> keySelector, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(isDescending) } )); } public static IQueryable AssumeOrderBy(this IQueryable source, Expression> keySelector, IComparer comparer, bool isDescending) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (IsLocalDebugSource(source)) { return source; } return source.Provider.CreateQuery( Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)), Expression.Constant(isDescending) } )); } public static IMultiQueryable Fork(this IQueryable source, Expression, IEnumerable>>> mapper) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IMultiEnumerable enumerables = HpcLinqEnumerable.Fork(source, mapper.Compile()); return new MultiQueryable(source, enumerables); } Expression expr = Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(R1), typeof(R2)), new Expression[] { source.Expression, Expression.Quote(mapper) } ); return new MultiQueryable(source, expr); } public static IMultiQueryable Fork(this IQueryable source, Expression, IEnumerable>>> mapper) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IMultiEnumerable enumerables = HpcLinqEnumerable.Fork(source, mapper.Compile()); return new MultiQueryable(source, enumerables); } Expression expr = Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(R1), typeof(R2), typeof(R3)), new Expression[] { source.Expression, Expression.Quote(mapper) } ); return new MultiQueryable(source, expr); } /// /// Compute two output datasets from one input dataset. /// /// The type of records of input dataset /// The type of records of first output dataset /// The type of records of second output dataset /// The input dataset /// The function applied to each record of the input /// An IMultiQueryable for the two output dataset public static IMultiQueryable Fork(this IQueryable source, Expression>> mapper) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IMultiEnumerable enumerables = HpcLinqEnumerable.Fork(source, mapper.Compile()); return new MultiQueryable(source, enumerables); } Expression expr = Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(R1), typeof(R2)), new Expression[] { source.Expression, Expression.Quote(mapper) } ); return new MultiQueryable(source, expr); } public static IMultiQueryable Fork(this IQueryable source, Expression>> mapper) { if (source == null) { throw new ArgumentNullException("source"); } if (IsLocalDebugSource(source)) { IMultiEnumerable enumerables = HpcLinqEnumerable.Fork(source, mapper.Compile()); return new MultiQueryable(source, enumerables); } Expression expr = Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T), typeof(R1), typeof(R2), typeof(R3)), new Expression[] { source.Expression, Expression.Quote(mapper) } ); return new MultiQueryable(source, expr); } public static IKeyedMultiQueryable Fork(this IQueryable source, Expression> keySelector, TKey[] keys) { if (source == null) { throw new ArgumentNullException("source"); } if (keySelector == null) { throw new ArgumentNullException("keySelector"); } if (keys == null) { throw new ArgumentNullException("keys"); } if (IsLocalDebugSource(source)) { IMultiEnumerable enumerables = HpcLinqEnumerable.Fork(source, keySelector.Compile(), keys); return new MultiQueryable(source, keys, enumerables); } Expression expr = Expression.Call( null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey)), new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(keys, typeof(TKey[])) } ); return new MultiQueryable(source, keys, expr); } internal static IQueryable ForkChoose(this IMultiQueryable source, int index) { if (source == null) { throw new ArgumentNullException("source"); } return source.Provider.CreateQuery( Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(T)), new Expression[] { source.Expression, Expression.Constant(index) })); } /// /// Specifies a DSC stream to be populated with data during query execution. /// /// The type of the records of the table /// The data source /// A DSC service /// A DSC stream name /// A query representing the output data. // Note: for both cluster&LocalDebug, we add a node to the query-tree // Submit/Materialize will process the ToDsc call in both cases. // This is good for consistency of LocalDebug & Cluser modes -- ie ToDsc is lazy in both cases. public static IQueryable ToDsc(this IQueryable source, string streamName) { if (source == null) { throw new ArgumentNullException("source"); } if (streamName == null) { throw new ArgumentNullException("streamName"); } if (!(source.Provider is DryadLinqProviderBase)) { //@@TODO[p2]: a "single-input" resource string should be used throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, 0), "source"); } HpcLinqContext context = HpcLinqContext.GetContext(source.Provider as DryadLinqProviderBase); MethodInfo nongenericMethod = typeof(HpcLinqQueryable) .GetMethod(ReflectedNames.DryadLinqIQueryable_ToDscWorker, BindingFlags.Static | BindingFlags.NonPublic); MethodInfo targetMethod = nongenericMethod.MakeGenericMethod(typeof(TSource)); return source.Provider.CreateQuery( Expression.Call( null, targetMethod, //((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Constant(context , typeof(HpcLinqContext)), Expression.Constant(streamName, typeof(string)) } )); } /// /// Specifies a HDFS stream to be populated with data during query execution. /// /// The type of the records of the table /// The data source /// A HDFS service /// A HDFS stream name /// A query representing the output data. // Note: for both cluster&LocalDebug, we add a node to the query-tree // Submit/Materialize will process the ToHdfs call in both cases. // This is good for consistency of LocalDebug & Cluser modes -- ie ToHdfs is lazy in both cases. public static IQueryable ToHdfs(this IQueryable source, string streamName) { if (source == null) { throw new ArgumentNullException("source"); } if (streamName == null) { throw new ArgumentNullException("streamName"); } if (!(source.Provider is DryadLinqProviderBase)) { //@@TODO[p2]: a "single-input" resource string should be used throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, 0), "source"); } HpcLinqContext context = HpcLinqContext.GetContext(source.Provider as DryadLinqProviderBase); MethodInfo nongenericMethod = typeof(HpcLinqQueryable) .GetMethod(ReflectedNames.DryadLinqIQueryable_ToHdfsWorker, BindingFlags.Static | BindingFlags.NonPublic); MethodInfo targetMethod = nongenericMethod.MakeGenericMethod(typeof(TSource)); return source.Provider.CreateQuery( Expression.Call( null, targetMethod, //((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Constant(context , typeof(HpcLinqContext)), Expression.Constant(streamName, typeof(string)) } )); } /// /// Specifies a DSC stream to be populated with data during query execution. /// /// /// This method is not intended for direct use. To prepare a plain enumerable for /// use with DryadLinq, call AsDryadQuery or AsDryadQueryPartitions. /// /// The type of the records of the table /// The data source /// A DSC service /// A DSC stream name /// A query representing the output data. // @@TODO[P1]: The above comments require that AsDryadQuery/AsDryadQueryPartitions exists.. that is a P1 work item. // In the meantime, a basic version of those methods is available in DryadLinqUnitTests. // // *visited by "LocalDebug-mode GetEnumerator()" // -- in cluster mode, we never enter this method.. DryadQueryGen just inspects the MethodCallExpression // -- in localDebug mode, we do enter this method, particularly via Linq-to-objects GetEnumerator. // // Behavior: // (LocalDebug mode) q.ToDsc().GetEnumerator() -> throws, as execution never occurred, so the output was not created. // (LocalDebug mode) var q1 = q.ToDsc();q1.Submit(); foreach(var x in q1) -> succeeds (as submit creates the data) // internal static IQueryable ToDscWorker(this IEnumerable source, HpcLinqContext context, string streamName) { // We want the following query to succeed reliably for both cluster and LocalDebug : // var q1 = q.ToDsc(".."); // q1.Submit(runtime); // foreach(var x in q1){ ... } // calls q1.GetEnumerator() // // For cluster execution, q1 becomes data-backed and so the call to GetEnumerator succeeds. // For local execution, we don't attach a "databacking DLQ" to the source // - if we did find a "data-backing DLQ" for the DSC node we would return that node. // - but we don't, so we fake it by looking for the existence of the output and if it exists, we // assume that we created it and treat it as though we had tracked it as the data-backing. // // @@BUG(low-severity): This logic could be spoofed if the dsc output already exists but wasn't created via // the expected call to Submit()/Materialize().. A possible cause is a previous run of almost exactly the same query. // Mitigation: User-education to not rely on auto-delete of output streams will avoid the issue and is a good idea anyway. // // (fix idea) reimplement all the Linq-to-objects operators ourseleves so that we have more control // during LocalDebug-mode. // // (fix idea) Introduce a new class DryadLinqQueryLocal. It uses AsQueryable.Provider as query provider // and has a data-backing field. May only be feasible if DryadLinqQuery is internal. IQueryable fakedDataBackingDLQ = null; try { if (context.DscService.FileSetExists(streamName)) { // if so, try to make a DLQ from it. fakedDataBackingDLQ = context.FromDsc(streamName); } } catch (DryadLinqException) { //suppress.. we expect this to occur if the dsc stream does exist, but cannot be loaded as a DLQ } if (fakedDataBackingDLQ != null) return fakedDataBackingDLQ; throw new DryadLinqException(HpcLinqErrorCode.ToDscUsedIncorrectly, String.Format(SR.ToDscUsedIncorrectly)); } /// /// Specifies a HDFS stream to be populated with data during query execution. /// /// /// This method is not intended for direct use. To prepare a plain enumerable for /// use with DryadLinq, call AsDryadQuery or AsDryadQueryPartitions. /// /// The type of the records of the table /// The data source /// A HDFS service /// A HDFS stream name /// A query representing the output data. // @@TODO[P1]: The above comments require that AsDryadQuery/AsDryadQueryPartitions exists.. that is a P1 work item. // In the meantime, a basic version of those methods is available in DryadLinqUnitTests. // // *visited by "LocalDebug-mode GetEnumerator()" // -- in cluster mode, we never enter this method.. DryadQueryGen just inspects the MethodCallExpression // -- in localDebug mode, we do enter this method, particularly via Linq-to-objects GetEnumerator. // // Behavior: // (LocalDebug mode) q.ToHdfs().GetEnumerator() -> throws, as execution never occurred, so the output was not created. // (LocalDebug mode) var q1 = q.ToHdfs();q1.Submit(); foreach(var x in q1) -> succeeds (as submit creates the data) // internal static IQueryable ToHdfsWorker(this IEnumerable source, HpcLinqContext context, string streamName) { // We want the following query to succeed reliably for both cluster and LocalDebug : // var q1 = q.ToHdfs(".."); // q1.Submit(runtime); // foreach(var x in q1){ ... } // calls q1.GetEnumerator() // // For cluster execution, q1 becomes data-backed and so the call to GetEnumerator succeeds. // For local execution, we don't attach a "databacking DLQ" to the source // - if we did find a "data-backing DLQ" for the DSC node we would return that node. // - but we don't, so we fake it by looking for the existence of the output and if it exists, we // assume that we created it and treat it as though we had tracked it as the data-backing. // // @@BUG(low-severity): This logic could be spoofed if the dsc output already exists but wasn't created via // the expected call to Submit()/Materialize().. A possible cause is a previous run of almost exactly the same query. // Mitigation: User-education to not rely on auto-delete of output streams will avoid the issue and is a good idea anyway. // // (fix idea) reimplement all the Linq-to-objects operators ourseleves so that we have more control // during LocalDebug-mode. // // (fix idea) Introduce a new class DryadLinqQueryLocal. It uses AsQueryable.Provider as query provider // and has a data-backing field. May only be feasible if DryadLinqQuery is internal. IQueryable fakedDataBackingDLQ = null; try { bool exists; using (HdfsInstance hdfs = new HdfsInstance(context.HdfsService)) { exists = hdfs.IsFileExists(streamName); } if (exists) { // if so, try to make a DLQ from it. fakedDataBackingDLQ = context.FromHdfs(streamName); } } catch (DryadLinqException) { //suppress.. we expect this to occur if the dsc stream does exist, but cannot be loaded as a DLQ } if (fakedDataBackingDLQ != null) return fakedDataBackingDLQ; throw new DryadLinqException(HpcLinqErrorCode.ToHdfsUsedIncorrectly, String.Format(SR.ToHdfsUsedIncorrectly)); } /// /// Submits the query and then waits for the job to complete /// /// If the job completes in error or is cancelled. /// If repeated errors occur while polling for status. /// The type of the records of the table /// The data source /// Information about the execution job. public static HpcLinqJobInfo SubmitAndWait(this IQueryable source) { HpcLinqJobInfo info = source.Submit(); info.Wait(); return info; } /// /// Submits the query for asynchronous execution. /// /// The type of the records of the table /// The data source /// The URI of the DSC file set to be created /// Information about the execution job. // @@TODO[P1]. Try to unify q.Submit() and the static Submit. They duplicate a fair bit of code. // Changing this method to work with untyped IQueryable (and not mention TSource) should // make it easy to forward the call to submit( new [] {source} ) public static HpcLinqJobInfo Submit(this IQueryable source) { if (source == null) { throw new ArgumentNullException("source"); } //Extract the context. if (!(source.Provider is DryadLinqProviderBase)) { //@@TODO[p2]: a "single-input" resource string should be used throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, 0), "source"); } HpcLinqContext context = HpcLinqContext.GetContext(source.Provider as DryadLinqProviderBase); if (IsLocalDebugSource(source)) { try { // if ToDsc is present, extract out the target, otherwise make an anonymous target // then ingress the data directly to DSC. MethodCallExpression mcExpr1 = source.Expression as MethodCallExpression; if (mcExpr1 != null && mcExpr1.Method.Name == ReflectedNames.DryadLinqIQueryable_ToDscWorker) { // visted by LocalDebug:: q2.ToDsc(...).Submit(...), eg Test3. LocalDebug_ProcessToDscExpression(context, mcExpr1); } else { // visited by (LocalDebug mode) q-nonToDsc.Submit(); string fileSetName = DataPath.MakeUniqueTemporaryDscFileSetName(); DscCompressionScheme outputScheme = context.Configuration.IntermediateDataCompressionScheme; DryadLinqMetaData metadata = DryadLinqMetaData.ForLocalDebug(context, typeof(TSource), fileSetName, outputScheme ); DataProvider.IngressTemporaryDataDirectlyToDsc(context, source, fileSetName, metadata, outputScheme); } return new HpcLinqJobInfo(HpcLinqJobInfo.JOBID_LOCALDEBUG, null, null, null); } catch (Exception e) { throw new DryadLinqException(HpcLinqErrorCode.CreatingDscDataFromLocalDebugFailed, String.Format(SR.CreatingDscDataFromLocalDebugFailed), e); } } if (!(source is DryadLinqQuery)) { //@@TODO[p2]: a "single-input" resource string should be used throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, 0), "source"); } // handle repeat submissions. if (((DryadLinqQuery)source).IsDataBacked) { // this query has already been submitted. throw new ArgumentException(string.Format(SR.AlreadySubmitted), "source"); } // sanity check that we have a normal DryadLinqQuery MethodCallExpression mcExpr = source.Expression as MethodCallExpression; if (mcExpr == null) { throw new ArgumentException(String.Format(SR.AtLeastOneOperatorRequired, 0), "source"); } if (!mcExpr.Method.IsStatic || !TypeSystem.IsQueryOperatorCall(mcExpr)) { //@@TODO[p2]: a "single-input" resource string should be used throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, 0), "source"); } if (mcExpr.Method.Name != ReflectedNames.DryadLinqIQueryable_ToDscWorker && mcExpr.Method.Name != ReflectedNames.DryadLinqIQueryable_ToHdfsWorker) { // Support for non-ToDscQuery.Submit() string tableName = DataPath.MakeUniqueTemporaryDscFileSetUri(context); mcExpr = (MethodCallExpression) source.Provider.CreateQuery( Expression.Call( null, typeof(HpcLinqQueryable).GetMethod(ReflectedNames.DryadLinqIQueryable_AnonymousDscPlaceholder, BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(typeof(TSource)), new Expression[] { source.Expression, Expression.Constant(tableName, typeof(string))} )).Expression; } // Execute the queries HpcLinqQueryGen dryadGen = new HpcLinqQueryGen(context, ((DryadLinqQuery)source).GetVertexCodeGen(), new Expression[] { mcExpr }); DryadLinqQuery[] tables = dryadGen.InvokeDryad(); tables[0].IsTemp = false; ((DryadLinqQuery)source).BackingDataDLQ = tables[0]; int jobId = tables[0].QueryExecutor.JobSubmission.GetJobId(); string[] targetUris = new [] {tables[0].DataSourceUri}; return new HpcLinqJobInfo(jobId, context.Configuration.HeadNode, tables[0].QueryExecutor, targetUris); } // inspect and process the trailing ToDsc() node in local-debug scenarios. private static void LocalDebug_ProcessToDscExpression(HpcLinqContext context, MethodCallExpression mcExpr1) { // get the dsc target out of the ToDsc node. DscService dsc = context.DscService; string fileSetName = (string)((ConstantExpression)mcExpr1.Arguments[2]).Value; // evaluate the source query before the ToDsc node. // WAS MethodCallExpression mce = ((MethodCallExpression)mcExpr1.Arguments[0]); // DIDN't handle constant expression for plain-data. Expression e = mcExpr1.Arguments[0]; DscCompressionScheme compressionScheme = context.Configuration.OutputDataCompressionScheme; ExecuteLocalExpressionAndIngressToDsc(context, e, fileSetName, compressionScheme); } // process the main data and push into DSC, used in local-debug scenarios. private static void ExecuteLocalExpressionAndIngressToDsc(HpcLinqContext context, Expression mce, string fileSetName, DscCompressionScheme compressionScheme) { ExpressionSimplifier> simplifier = new ExpressionSimplifier>(); IEnumerable sourceData = simplifier.Eval(mce); // stuff the data into DSC DryadLinqMetaData metadata = DryadLinqMetaData.ForLocalDebug(context, typeof(TSource), fileSetName, compressionScheme); DataProvider.IngressDataDirectlyToDsc(context, sourceData, fileSetName, metadata, compressionScheme); } // this method is never directly executed // it's only use is as a placeholder in an expression tree for the scenario: query-nonDsc.Submit() // This appears in expression trees in the same place that "ToDscWorker" would otherwise appear. internal static DryadLinqQuery AnonymousDscTarget__Placeholder(this IEnumerable source, string dscFileSetUri) { throw new InvalidOperationException(); } /// /// Submits a collection of HPC LINQ queries for execution. /// /// Queries to execute. /// Job information for tracking the execution. /// /// Every item in sources must be an HPC LINQ IQueryable object that terminates with ToDsc() /// Only one job will be executed, but the job will produce the output associated with each item in sources. /// public static HpcLinqJobInfo Submit(params IQueryable[] sources) { if (sources == null) { throw new ArgumentNullException("sources"); } if(sources.Length == 0) { //@@TODO[p2]: localize message. throw new ArgumentException("sources is empty", "sources"); } HpcLinqContext commonContext = CheckSourcesAndGetCommonContext(sources); return HpcLinqQueryable.Materialize(commonContext, sources); } /// /// Submits a collection of HPC LINQ queries for execution and waits for the job to complete/ /// /// If the job completes in error or is cancelled. /// If repeated errors occur while polling for status. /// The type of the records of the table /// The data source /// Information about the execution job. /// /// Every item in sources must be an HPC LINQ IQueryable object that terminates with ToDsc() /// Only one job will be executed, but the job will produce the output associated with each item in sources. /// public static HpcLinqJobInfo SubmitAndWait(params IQueryable[] sources) { if (sources == null) { throw new ArgumentNullException("sources"); } if (sources.Length == 0) { throw new ArgumentException("sources is empty", "sources"); } HpcLinqContext commonContext = CheckSourcesAndGetCommonContext(sources); HpcLinqJobInfo info = HpcLinqQueryable.Materialize(commonContext, sources); info.Wait(); return info; } private static HpcLinqContext CheckSourcesAndGetCommonContext(IQueryable[] sources) { Debug.Assert(sources != null && sources.Length > 0); for (int i = 0; i < sources.Length; i++) { if (sources[i] == null) { //@@TODO[p1]: localize throw new ArgumentException(string.Format("An item in sources[] was null. sources[{0}]", i), "sources"); } // sanity check that we have normal DryadLinqQuery objects if (!(sources[i].Provider is DryadLinqProviderBase)) { throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, i), "sources"); } } //check for duplicate query objects HashSet repeatedQueryDetector = new HashSet(); for (int i = 0; i < sources.Length; i++) { var q = sources[i]; if (repeatedQueryDetector.Contains(q)) { throw new ArgumentException(string.Format(SR.SameQuerySubmittedMultipleTimesInMaterialize), string.Format("sources[{0}]", i)); } repeatedQueryDetector.Add(q); } //Check the queries all use the same context HpcLinqContext[] contexts = sources.Select(src => HpcLinqContext.GetContext(src.Provider as DryadLinqProviderBase)).ToArray(); if (contexts.Distinct().Count() != 1) { //@@TODO[p1]: localize message throw new ArgumentException("Each query must be created from the same HpcLinqContext object", "sources"); } HpcLinqContext commonContext = contexts[0]; return commonContext; } /// /// Force the execution of a list of queries and create the partitioned tables for the /// results of the queries. /// /// The list of lazy tables to be materialized /// A list of partitioned tables internal static HpcLinqJobInfo Materialize(HpcLinqContext context, params IQueryable[] sources) { if (context.Configuration.LocalDebug) { //@@TODO[P1]: force streams to be be temporary if automatically named. Not doing this might be considered a bug. foreach (var source in sources) { MethodCallExpression mcExpr1 = source.Expression as MethodCallExpression; if (mcExpr1 == null) { //normally we have a method call, but IDryadLinqQueryable.HashPartition() will just return source in //localDebug mode. hence ctx.Submit(src.HashPartition()) will just present src here. Debug.Assert(source.Expression is ConstantExpression, "mcExpr1 should be MethodCallExpression or ConstantExpression"); } if (mcExpr1 != null && mcExpr1.Method.Name == ReflectedNames.DryadLinqIQueryable_ToDscWorker) { // visted by LocalDebug:: Materialize( {q2.ToDsc(...)} ), eg Test5. var method = typeof(HpcLinqQueryable) .GetMethod(ReflectedNames.HpcLinqQueryable_LocalDebug_ProcessToDscExpression, BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(source.ElementType); try { method.Invoke(null, new object[] { context, mcExpr1 }); } catch (TargetInvocationException tie) { if (tie.InnerException != null) throw tie.InnerException; // unwrap and rethrow original exception else throw; // this shouldn't occur.. but just in case. } } else { // visted by LocalDebug:: Materialize( {q2.Non-ToDsc(...)} ), eg Test6. string tableName = DataPath.MakeUniqueTemporaryDscFileSetName(); DscCompressionScheme compressionScheme = context.Configuration.IntermediateDataCompressionScheme; var method = typeof(HpcLinqQueryable) .GetMethod(ReflectedNames.HpcLinqQueryable_ExecuteLocalExpressionAndIngressToDsc, BindingFlags.NonPublic | BindingFlags.Static) .MakeGenericMethod(source.ElementType); try { method.Invoke(null, new object[] { context, source.Expression, tableName, compressionScheme }); } catch (TargetInvocationException tie) { if (tie.InnerException != null) throw tie.InnerException; // unwrap and rethrow original exception else throw; // this shouldn't occur.. but just in case. } } } return new HpcLinqJobInfo(HpcLinqJobInfo.JOBID_LOCALDEBUG, null, null, null); } else { // If the sources were not terminated with ToDsc(), do this now and provide a temporary output name Expression[] qList = new Expression[sources.Length]; bool[] isTemps = new bool[sources.Length]; for (int i = 0; i < sources.Length; i++) { isTemps[i] = false; MethodCallExpression mcExpr = sources[i].Expression as MethodCallExpression; // sanity check that we have a normal DryadLinqQuery if (!(sources[i] is DryadLinqQuery)) { throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, i), string.Format("sources[{0}]", i)); } // check that the query has not already been submitted. if (((DryadLinqQuery)sources[i]).IsDataBacked) { throw new ArgumentException(string.Format(SR.AlreadySubmittedInMaterialize), string.Format("sources[{0}]", i)); } // more checks that we have a normal, unsubmitted, non-trivial DryadLinqQuery if (!(sources[i] is DryadLinqQuery) || mcExpr == null || !mcExpr.Method.IsStatic || !TypeSystem.IsQueryOperatorCall(mcExpr)) { throw new ArgumentException(String.Format(SR.NotAHpcLinqQuery, i), string.Format("sources[{0}]", i)); } if (mcExpr.Method.Name != ReflectedNames.DryadLinqIQueryable_ToDscWorker) { isTemps[i] = true; string tableName = DataPath.MakeUniqueTemporaryDscFileSetUri(context); MethodInfo minfo = typeof(HpcLinqQueryable) .GetMethod(ReflectedNames.DryadLinqIQueryable_AnonymousDscPlaceholder, BindingFlags.Static | BindingFlags.NonPublic); Type elemType = mcExpr.Type.GetGenericArguments()[0]; minfo = minfo.MakeGenericMethod(elemType); mcExpr = Expression.Call(minfo, mcExpr, Expression.Constant(tableName)); } qList[i] = mcExpr; } // Normal cluster execution -- prepare and submit the query to Dryad. // Execute the queries, which are all now terminated by ToDsc() VertexCodeGen vertexCodeGen = ((DryadLinqQuery)sources[0]).GetVertexCodeGen(); HpcLinqQueryGen queryGen = new HpcLinqQueryGen(context, vertexCodeGen, qList); DryadLinqQuery[] tables = queryGen.InvokeDryad(); // Store the results in the queries for (int j = 0; j < sources.Length; j++) { tables[j].IsTemp = isTemps[j]; ((DryadLinqQuery)sources[j]).BackingDataDLQ = tables[j]; } // return a runtimeInfo. int jobId = tables[0].QueryExecutor.JobSubmission.GetJobId(); string[] targetUris = new string[tables.Length]; for (int i = 0; i < tables.Length; i++) { targetUris[i] = tables[i].DataSourceUri; } return new HpcLinqJobInfo(jobId, context.Configuration.HeadNode, tables[0].QueryExecutor, targetUris); } } } }