private DryadQueryNode VisitPartitionOp(string opName, QueryNodeInfo source, QueryNodeType nodeType, Expression controlExpr, MethodCallExpression queryExpr) { DryadQueryNode resNode; if (nodeType == QueryNodeType.TakeWhile && controlExpr.Type.GetGenericArguments().Length != 2) { // The "indexed" version. resNode = this.Visit(source); // The following block used to be skipped for resNode.OutputPartition.Count == 1, // which causes compilation error (bug 13593) // @@TODO[p3] : implement a working optimization for nPartition==1 that calls // directly to Linq TakeWhile. // Note: the test is: if (resNode.IsDynamic || resNode.OutputPartition.Count > 1) { resNode.IsForked = true; bool isLong = (queryExpr.Method.Name == "LongTakeWhile"); DryadQueryNode offsetNode = this.CreateOffset(isLong, queryExpr, resNode); // Create (x, y) => GroupIndexedTakeWhile(x, y, controlExpr) Type ptype1 = typeof(IEnumerable<>).MakeGenericType(resNode.OutputTypes[0]); Type ptype2 = typeof(IEnumerable<>).MakeGenericType(typeof(IndexedValue<long>)); ParameterExpression param1 = Expression.Parameter(ptype1, HpcLinqCodeGen.MakeUniqueName("x")); ParameterExpression param2 = Expression.Parameter(ptype2, HpcLinqCodeGen.MakeUniqueName("y")); string methodName = "GroupIndexed" + queryExpr.Method.Name; MethodInfo minfo = typeof(HpcLinqEnumerable).GetMethod(methodName); minfo = minfo.MakeGenericMethod(resNode.OutputTypes[0]); Expression body = Expression.Call(minfo, param1, param2, controlExpr); Type type = typeof(Func<,,>).MakeGenericType(ptype1, ptype2, body.Type); LambdaExpression procFunc = Expression.Lambda(type, body, param1, param2); resNode = new DryadApplyNode(procFunc, queryExpr, resNode, offsetNode); } } else if (!source.IsForked && (nodeType == QueryNodeType.Take || nodeType == QueryNodeType.TakeWhile) && (source.OperatorName == "OrderBy" || source.OperatorName == "OrderByDescending")) { resNode = this.Visit(source.children[0].child); bool isDescending = (source.OperatorName == "OrderByDescending"); MethodCallExpression sourceQueryExpr = (MethodCallExpression)source.queryExpression; LambdaExpression keySelectExpr = HpcLinqExpression.GetLambda(sourceQueryExpr.Arguments[1]); Expression comparerExpr = null; if (sourceQueryExpr.Arguments.Count == 3) { comparerExpr = sourceQueryExpr.Arguments[2]; } resNode = this.PromoteConcat( source.children[0].child, resNode, delegate(DryadQueryNode x) { DryadQueryNode y = new DryadOrderByNode(keySelectExpr, comparerExpr, isDescending, sourceQueryExpr, x); return FirstStagePartitionOp(opName, nodeType, controlExpr, queryExpr, y); }); if (resNode.IsDynamic || resNode.OutputPartition.Count > 1) { // Need a mergesort resNode = new DryadMergeNode(keySelectExpr, comparerExpr, isDescending, false, sourceQueryExpr, resNode); } } else { resNode = this.Visit(source); if (nodeType == QueryNodeType.Take || nodeType == QueryNodeType.TakeWhile) { resNode = this.PromoteConcat( source, resNode, x => FirstStagePartitionOp(opName, nodeType, controlExpr, queryExpr, x)); } } resNode = new DryadPartitionOpNode(opName, nodeType, controlExpr, false, queryExpr, resNode); return resNode; }
internal virtual string Visit(DryadPartitionOpNode node, CodeMemberMethod vertexMethod, string[] readerNames, string[] writerNames) { return node.AddVertexCode(vertexMethod, readerNames, writerNames); }