static async Task Main(string[] args) { // get connected string url = ConfigurationManager.AppSettings["url"]; if ((!url.EndsWith("/")) && (!url.EndsWith("\\"))) { url += "/"; } Console.Out.WriteLine($"Connecting to URL {url}"); client = new WindwardClient(new Uri(url)); VersionInfo version = await client.GetVersion(); Console.Out.WriteLine($"REST server version = {version}"); // if no arguments, then we list out the usage. if (args.Length < 2) { DisplayUsage(); return; } // the try here is so we can print out an exception if it is thrown. This code does minimal error checking and no other // exception handling to keep it simple & clear. try { Console.Out.WriteLine("Running in {0}-bit mode", IntPtr.Size * 8); // parse the arguments passed in. This method makes no calls to Windward, it merely organizes the passed in arguments. CommandLine cmdLine = CommandLine.Factory(args); // This turns on log4net logging. You can also call log4net.Config.XmlConfigurator.Configure(); directly. // If you do not make this call, then there will be no logging (which you may want off). var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()); XmlConfigurator.Configure(logRepository, new FileInfo("RunReport.config")); logWriter.Info($"Starting RunReport ({string.Join(", ", args)})"); DateTime startTime = DateTime.Now; // run one report if (!cmdLine.IsPerformance) { PerfCounters perfCounters = await RunOneReport(cmdLine, args.Length == 2); PrintPerformanceCounter(startTime, perfCounters, false); } else { string dirReports = Path.GetDirectoryName(Path.GetFullPath(cmdLine.ReportFilename)) ?? ""; if (!Directory.Exists(dirReports)) { Console.Error.WriteLine($"The directory {dirReports} does not exist"); return; } // drop out threads - twice the number of cores. int numThreads = cmdLine.NumThreads; numReportsRemaining = cmdLine.NumReports; ReportWorker[] workers = new ReportWorker[numThreads]; for (int ind = 0; ind < numThreads; ind++) { workers[ind] = new ReportWorker(ind, new CommandLine(cmdLine)); } Task[] threads = new Task[numThreads]; for (int ind = 0; ind < numThreads; ind++) { threads[ind] = workers[ind].DoWork(); } Console.Out.WriteLine($"Start time: {startTime.ToLongTimeString()}, {numThreads} threads, {cmdLine.NumReports} reports"); Console.Out.WriteLine(); for (int ind = 0; ind < numThreads; ind++) { threads[ind].Start(); } // we wait await Task.WhenAll(threads); PerfCounters perfCounters = new PerfCounters(); for (int ind = 0; ind < numThreads; ind++) { perfCounters.Add(workers[ind].perfCounters); } Console.Out.WriteLine(); PrintPerformanceCounter(startTime, perfCounters, true); } } catch (Exception ex) { logWriter.Error("RunReport", ex); string indent = " "; Console.Error.WriteLine(); Console.Error.WriteLine("Error(s) running the report"); while (ex != null) { Console.Error.WriteLine($"{indent}Error: {ex.Message} ({ex.GetType().FullName})\n{indent} stack: {ex.StackTrace}\n"); ex = ex.InnerException; indent += " "; } throw; } }
public ReportWorker(int threadNum, CommandLine cmdLine) { this.threadNum = threadNum; this.cmdLine = cmdLine; perfCounters = new PerfCounters(); }
private static async Task <PerfCounters> RunOneReport(CommandLine cmdLine, bool preservePodFraming) { DateTime startTime = DateTime.Now; PerfCounters perfCounters = new PerfCounters(); // Create the template object, based on the file extension Template.OutputFormatEnum formatOutput = Path.GetExtension(cmdLine.ReportFilename).Substring(1).GetEnumFromValue <Template.OutputFormatEnum>(); Template.FormatEnum formatTemplate = Path.GetExtension(cmdLine.TemplateFilename).Substring(1).GetEnumFromValue <Template.FormatEnum>(); Template template = new Template(formatOutput, File.ReadAllBytes(cmdLine.TemplateFilename), formatTemplate); template.TrackErrors = cmdLine.VerifyFlag; if (!string.IsNullOrEmpty(cmdLine.Locale)) { template.Properties.Add(new Property("report.locale", cmdLine.Locale)); } foreach (KeyValuePair <string, object> pair in cmdLine.Parameters) { template.Parameters.Add(new Parameter(pair.Key, pair.Value)); } // Now for each datasource, we apply it to the report. This is complex because it handles all datasource types foreach (CommandLine.DatasourceInfo dsInfo in cmdLine.Datasources) { // build the datasource switch (dsInfo.Type) { // An XPATH 2.0 datasource. case CommandLine.DatasourceInfo.TYPE.XML: if (!cmdLine.IsPerformance) { if (string.IsNullOrEmpty(dsInfo.SchemaFilename)) { Console.Out.WriteLine(string.Format("XPath 2.0 datasource: {0}", dsInfo.Filename)); } else { Console.Out.WriteLine(string.Format("XPath 2.0 datasource: {0}, schema {1}", dsInfo.Filename, dsInfo.SchemaFilename)); } } if (string.IsNullOrEmpty(dsInfo.SchemaFilename)) { template.Datasources.Add(new Xml_20DataSource(dsInfo.Name, File.ReadAllBytes(dsInfo.ExConnectionString), null)); } else { template.Datasources.Add(new Xml_20DataSource(dsInfo.Name, File.ReadAllBytes(dsInfo.ExConnectionString), File.ReadAllBytes(dsInfo.SchemaFilename))); } break; // An XPATH 1.0 datasource. case CommandLine.DatasourceInfo.TYPE.XPATH_1: if (!cmdLine.IsPerformance) { if (string.IsNullOrEmpty(dsInfo.SchemaFilename)) { Console.Out.WriteLine(string.Format("XPath 1.0 datasource: {0}", dsInfo.Filename)); } else { Console.Out.WriteLine(string.Format("XPath 1.0 datasource: {0}, schema {1}", dsInfo.Filename, dsInfo.SchemaFilename)); } } if (string.IsNullOrEmpty(dsInfo.SchemaFilename)) { template.Datasources.Add(new Xml_10DataSource(dsInfo.Name, File.ReadAllBytes(dsInfo.ExConnectionString), null)); } else { template.Datasources.Add(new Xml_10DataSource(dsInfo.Name, File.ReadAllBytes(dsInfo.ExConnectionString), File.ReadAllBytes(dsInfo.SchemaFilename))); } break; case CommandLine.DatasourceInfo.TYPE.JSON: if (!cmdLine.IsPerformance) { Console.Out.WriteLine($"JSON datasource: {dsInfo.Filename}"); } template.Datasources.Add(new JsonDataSource(dsInfo.Name, File.ReadAllBytes(dsInfo.ExConnectionString))); break; // An OData datasource. case CommandLine.DatasourceInfo.TYPE.ODATA: if (!cmdLine.IsPerformance) { Console.Out.WriteLine(string.Format("OData datasource: {0}", dsInfo.Filename)); } template.Datasources.Add(new ODataDataSource(dsInfo.Name, dsInfo.ExConnectionString)); break; // A SalesForce datasource. case CommandLine.DatasourceInfo.TYPE.SFORCE: if (!cmdLine.IsPerformance) { Console.Out.WriteLine(string.Format("SalesForce datasource: {0}", dsInfo.Filename)); } template.Datasources.Add(new SalesforceDataSource(dsInfo.Name, dsInfo.ExConnectionString)); break; case CommandLine.DatasourceInfo.TYPE.SQL: if (!cmdLine.IsPerformance) { Console.Out.WriteLine(string.Format("{0} datasource: {1}", dsInfo.SqlDriverInfo.Name, dsInfo.ConnectionString)); } template.Datasources.Add(new SqlDataSource(dsInfo.Name, dsInfo.SqlDriverInfo.Classname, dsInfo.ConnectionString)); break; default: throw new ArgumentException(string.Format("Unknown datasource type {0}", dsInfo.Type)); } } if (!cmdLine.IsPerformance) { Console.Out.WriteLine("Calling REST engine to start generating report"); } // we have nothing else to do, so we wait till we get the result. Document document = await client.PostDocument(template); string guid = document.Guid; if (!cmdLine.IsPerformance) { Console.Out.WriteLine($"REST Engine has accepted job {guid}"); } // wait for it to complete // instead of this you can use: template.Callback = "http://localhost/alldone/{guid}"; HttpStatusCode status = await client.GetDocumentStatus(guid); while (status == HttpStatusCode.Created || status == HttpStatusCode.Accepted) { await Task.Delay(100); status = await client.GetDocumentStatus(guid); } // we have nothing else to do, so we wait till we get the result. document = await client.GetDocument(guid); // delete it off the server await client.DeleteDocument(guid); if (!cmdLine.IsPerformance) { Console.Out.WriteLine($"REST Engine has completed job {document.Guid}"); } perfCounters.timeProcess = DateTime.Now - startTime; perfCounters.numPages = document.NumberOfPages; perfCounters.numReports = 1; PrintVerify(document); // save if (document.Data != null) { File.WriteAllBytes(cmdLine.ReportFilename, document.Data); } else { { string prefix = Path.GetFileNameWithoutExtension(cmdLine.ReportFilename); string directory = Path.GetDirectoryName(Path.GetFullPath(cmdLine.ReportFilename)); string extension = Path.GetExtension(cmdLine.ReportFilename); for (int fileNumber = 0; fileNumber < document.Pages.Length; fileNumber++) { string filename = Path.Combine(directory, prefix + "_" + fileNumber + extension); filename = Path.GetFullPath(filename); File.WriteAllBytes(filename, document.Pages[fileNumber]); Console.Out.WriteLine(" document page written to " + filename); } } } if (!cmdLine.IsPerformance) { Console.Out.WriteLine($"{cmdLine.ReportFilename} built, {document.NumberOfPages} pages long."); Console.Out.WriteLine($"Elapsed time: {DateTime.Now - startTime}"); } if (cmdLine.Launch) { Console.Out.WriteLine(string.Format("launching report {0}", cmdLine.ReportFilename)); System.Diagnostics.Process.Start(cmdLine.ReportFilename); } return(perfCounters); }
public void Add(PerfCounters pc) { timeProcess += pc.timeProcess; numReports += pc.numReports; numPages += pc.numPages; }