// Add a new vertex method to the Dryad vertex class internal CodeMemberMethod AddVertexMethod(DryadQueryNode node) { CodeMemberMethod vertexMethod = new CodeMemberMethod(); vertexMethod.Attributes = MemberAttributes.Public | MemberAttributes.Static; vertexMethod.ReturnType = new CodeTypeReference(typeof(int)); vertexMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "args")); vertexMethod.Name = MakeUniqueName(node.NodeType.ToString()); CodeTryCatchFinallyStatement tryBlock = new CodeTryCatchFinallyStatement(); string startedMsg = "DryadLinqLog.Add(\"Vertex " + vertexMethod.Name + " started at {0}\", DateTime.Now.ToString(\"MM/dd/yyyy HH:mm:ss.fff\"))"; vertexMethod.Statements.Add(new CodeSnippetExpression(startedMsg)); // We need to call AddCopyResourcesMethod() vertexMethod.Statements.Add(new CodeSnippetExpression("CopyResources()")); if (StaticConfig.LaunchDebugger) { // If static config requests it, we do an unconditional Debugger.Launch() at vertex entry. // Currently this isn't used because StaticConfig.LaunchDebugger is hardcoded to false System.Console.WriteLine("Launch debugger: may block application"); CodeExpression launchExpr = new CodeSnippetExpression("System.Diagnostics.Debugger.Launch()"); vertexMethod.Statements.Add(new CodeExpressionStatement(launchExpr)); } else { // Otherwise (the default behavior), we first make sure we emit the debug check helper static method // and add a call to it at vertex entry. This helper checks an environment variable to decide whether // to launch the debugger, wait for a manual attach or simply skip straigt into vertex code. EnsureDebuggerHelperMethodEmitted(); CodeMethodInvokeExpression debuggerCheckExpr = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(VertexClassName), DebugHelperMethodName)); vertexMethod.Statements.Add(new CodeExpressionStatement(debuggerCheckExpr)); } vertexMethod.Statements.Add(MakeDryadVertexParamsDecl(node)); vertexMethod.Statements.Add(SetDryadVertexParamField("VertexStageName", vertexMethod.Name)); vertexMethod.Statements.Add(SetDryadVertexParamField("UseLargeBuffer", node.UseLargeWriteBuffer)); vertexMethod.Statements.Add(SetDryadVertexParamField("KeepInputPortOrder", node.KeepInputPortOrder())); // Push the parallel-code settings into HpcLinqVertex bool multiThreading = this.m_context.Configuration.AllowConcurrentUserDelegatesInSingleProcess; vertexMethod.Statements.Add(SetDryadVertexParamField("MultiThreading", multiThreading)); vertexMethod.Statements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(DLVTypeExpr, "s_multiThreading"), new CodePrimitiveExpression(multiThreading))); vertexMethod.Statements.Add(MakeDryadEnvDecl(node)); Type[] outputTypes = node.OutputTypes; string[] writerNames = new string[outputTypes.Length]; for (int i = 0; i < outputTypes.Length; i++) { CodeVariableDeclarationStatement writerDecl = MakeDryadWriterDecl(outputTypes[i], this.GetStaticFactoryName(outputTypes[i])); vertexMethod.Statements.Add(writerDecl); writerNames[i] = writerDecl.Name; } // Add side readers: node.AddSideReaders(vertexMethod); // Generate code based on the node type: switch (node.NodeType) { case QueryNodeType.Where: case QueryNodeType.OrderBy: case QueryNodeType.Distinct: case QueryNodeType.Skip: case QueryNodeType.SkipWhile: case QueryNodeType.Take: case QueryNodeType.TakeWhile: case QueryNodeType.Merge: case QueryNodeType.Select: case QueryNodeType.SelectMany: case QueryNodeType.GroupBy: case QueryNodeType.BasicAggregate: case QueryNodeType.Aggregate: case QueryNodeType.Contains: case QueryNodeType.Join: case QueryNodeType.GroupJoin: case QueryNodeType.Union: case QueryNodeType.Intersect: case QueryNodeType.Except: case QueryNodeType.RangePartition: case QueryNodeType.HashPartition: case QueryNodeType.Apply: case QueryNodeType.Fork: case QueryNodeType.Dynamic: { Type[] inputTypes = node.InputTypes; string[] sourceNames = new string[inputTypes.Length]; for (int i = 0; i < inputTypes.Length; i++) { CodeVariableDeclarationStatement readerDecl = MakeDryadReaderDecl(inputTypes[i], this.GetStaticFactoryName(inputTypes[i])); vertexMethod.Statements.Add(readerDecl); sourceNames[i] = readerDecl.Name; } string sourceToSink = this.m_vertexCodeGen.AddVertexCode(node, vertexMethod, sourceNames, writerNames); if (sourceToSink != null && (node.NodeType == QueryNodeType.Dynamic || node.Parents.Count > 0)) { CodeExpression sinkExpr = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression(writerNames[0]), "WriteItemSequence", new CodeVariableReferenceExpression(sourceToSink)); vertexMethod.Statements.Add(sinkExpr); } break; } case QueryNodeType.Super: { string sourceToSink = this.m_vertexCodeGen.AddVertexCode(node, vertexMethod, null, writerNames); if (sourceToSink != null && node.Parents.Count > 0) { CodeExpression sinkExpr = new CodeMethodInvokeExpression( new CodeVariableReferenceExpression(writerNames[0]), "WriteItemSequence", new CodeVariableReferenceExpression(sourceToSink)); vertexMethod.Statements.Add(sinkExpr); } break; } default: { //@@TODO: this should not be reachable. could change to Assert/InvalidOpEx throw new DryadLinqException(HpcLinqErrorCode.Internal, String.Format(SR.AddVertexNotHandled, node.NodeType)); } } string completedMsg = "DryadLinqLog.Add(\"Vertex " + vertexMethod.Name + " completed at {0}\", DateTime.Now.ToString(\"MM/dd/yyyy HH:mm:ss.fff\"))"; vertexMethod.Statements.Add(new CodeSnippetExpression(completedMsg)); // add a catch block CodeCatchClause catchBlock = new CodeCatchClause("e"); CodeTypeReferenceExpression errorReportClass = new CodeTypeReferenceExpression("HpcLinqVertexEnv"); CodeMethodReferenceExpression errorReportMethod = new CodeMethodReferenceExpression(errorReportClass, "ReportVertexError"); CodeVariableReferenceExpression exRef = new CodeVariableReferenceExpression(catchBlock.LocalName); catchBlock.Statements.Add(new CodeMethodInvokeExpression(errorReportMethod, exRef)); tryBlock.CatchClauses.Add(catchBlock); // wrap the entire vertex method in a try/catch block tryBlock.TryStatements.AddRange(vertexMethod.Statements); vertexMethod.Statements.Clear(); vertexMethod.Statements.Add(tryBlock); // Always add "return 0", to make CLR hosting happy... vertexMethod.Statements.Add(new CodeMethodReturnStatement(ZeroExpr)); this.m_dryadVertexClass.Members.Add(vertexMethod); return vertexMethod; }
private bool KeepInputPortOrder(DryadQueryNode curNode) { if (curNode.SuperNode == this) { if (curNode.KeepInputPortOrder()) { return true; } foreach (DryadQueryNode child in curNode.Children) { if (this.KeepInputPortOrder(child)) { return true; } } } return false; }