public static async Task <ConvertFileSystemToGraphResult> ConvertFileSystemToGraphAsyncTask(string root, int asyncFileReadBlockSize, bool enableHash, IConvertFileSystemToGraphProgress?convertFileSystemToGraphProgress, Persistence <IInsertResultsAbstract>?convertFileSystemToGraphPersistence, PickAndSave <IInsertResultsAbstract>?convertFileSystemToGraphPickAndSave, CancellationToken cancellationToken) {
async Task DoLoopAsync(string inputLine) { // check CancellationToken to see if this task is canceled CheckAndHandleCancellationToken(1); logger.LogDebug(uiLocalizer["{0} {1} inputLineString = {2}", "Console01BackgroundService", "DoLoopAsync", inputLine]); // Echo to stdOut the line that came in on stdIn mesg.Append(uiLocalizer["You selected: {0}", inputLine]); #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } mesg.Clear(); } #endregion #region tempout switch (inputLine) { case "1": // ToDo: Get these from the appConfiguration var rootString = appConfiguration.GetValue <string>(appStringConstants.RootStringConfigRootKey, appStringConstants.RootStringDefault); var asyncFileReadBlockSize = appConfiguration.GetValue <int>(appStringConstants.AsyncFileReadBlockSizeConfigRootKey, int.Parse(appStringConstants.AsyncFileReadBlockSizeDefault)); // ToDo: should validate in case the appStringConstants assembly is messed up? var enableHash = appConfiguration.GetValue <bool>(appStringConstants.EnableHashBoolConfigRootKey, bool.Parse(appStringConstants.EnableHashBoolConfigRootKeyDefault)); // ToDo: should validate in case the appStringConstants assembly is messed up? var enableProgress = appConfiguration.GetValue <bool>(appStringConstants.EnableProgressBoolConfigRootKey, bool.Parse(appStringConstants.EnableProgressBoolDefault)); // ToDo: should validate in case the appStringConstants assembly is messed up? var enablePersistence = appConfiguration.GetValue <bool>(appStringConstants.EnablePersistenceBoolConfigRootKey, bool.Parse(appStringConstants.EnablePersistenceBoolDefault)); // ToDo: should validate in case the appStringConstants assembly is messed up? var enablePickAndSave = appConfiguration.GetValue <bool>(appStringConstants.EnablePickAndSaveBoolConfigRootKey, bool.Parse(appStringConstants.EnablePickAndSaveBoolDefault)); // ToDo: should validate in case the appStringConstants assembly is messed up? var temporaryDirectoryBase = appConfiguration.GetValue <string>(appStringConstants.TemporaryDirectoryBaseConfigRootKey, appStringConstants.TemporaryDirectoryBaseDefault); var WithPersistenceNodeFileRelativePath = appConfiguration.GetValue <string>(appStringConstants.WithPersistenceNodeFileRelativePathConfigRootKey, appStringConstants.WithPersistenceNodeFileRelativePathDefault); var WithPersistenceEdgeFileRelativePath = appConfiguration.GetValue <string>(appStringConstants.WithPersistenceEdgeFileRelativePathConfigRootKey, appStringConstants.WithPersistenceEdgeFileRelativePathDefault); var filePathsPersistence = new string[2] { temporaryDirectoryBase + WithPersistenceNodeFileRelativePath, temporaryDirectoryBase + WithPersistenceEdgeFileRelativePath }; var WithPickAndSaveNodeFileRelativePath = appConfiguration.GetValue <string>(appStringConstants.WithPickAndSaveNodeFileRelativePathConfigRootKey, appStringConstants.WithPickAndSaveNodeFileRelativePathDefault); var filePathsPickAndSave = new string[1] { temporaryDirectoryBase + WithPickAndSaveNodeFileRelativePath }; mesg.Append(uiLocalizer["Running PartitionInfoEx Extension Function ConvertFileSystemToObjectGraph, on rootString {0} with an asyncFileReadBlockSize of {1} with hashing enabled: {2} ; progress enabled: {3} ; persistence enabled: {5} ; pickAndSave enabled: {4}", rootString, asyncFileReadBlockSize, enableHash, enableProgress, enablePersistence, enablePickAndSave]); if (enablePersistence) { mesg.Append(Environment.NewLine); mesg.Append(uiLocalizer[" persistence filePaths: {0}", string.Join(",", filePathsPersistence)]); } if (enablePickAndSave) { mesg.Append(Environment.NewLine); mesg.Append(uiLocalizer[" pickAndSave filePaths {0}", string.Join(",", filePathsPickAndSave)]); } if (enableProgress) { mesg.Append(Environment.NewLine); mesg.Append(uiLocalizer[" progressReporting TBD{0}", "ProgressReportingDataStructureDetails"]); } #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } mesg.Clear(); } #endregion #region ProgressReporting setup ConvertFileSystemToGraphProgress?convertFileSystemToGraphProgress; if (enableProgress) { convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress(); } else { convertFileSystemToGraphProgress = null; } #endregion #region PersistenceViaFiles setup // Ensure the Node and Edge files are empty and can be written to // Call the SetupViaFileFuncBuilder here, execute the Func that comes back, with filePaths as the argument // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files //ToDo: add exception handling if the setup function fails ISetupViaFileResults setupResultsPersistence; try { setupResultsPersistence = PersistenceStaticExtensions.SetupViaFileFuncBuilder()(new SetupViaFileData(filePathsPersistence)); } catch (System.IO.IOException ex) { // prepare message for UI interface // ToDo: custom exception, and include its message here mesg.Append(uiLocalizer["IOException trying to setup PersistenceViaFiles"]); #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } mesg.Clear(); } #endregion // Throw exception, Cancel the entire service (internal CTS), or swallow and Continue (possibly offering hints as to resolution), client's choice throw ex; // internalCancellationTokenSource.Signal ???? // or just continue and let the user make another selection or go fix the problem //break; } // Create an insertFunc that references the local variable setupResults, closing over it var insertFunc = new Func <IEnumerable <IEnumerable <object> >, IInsertViaFileResults>((insertData) => { int numberOfDatas = insertData.ToArray().Length; int numberOfStreamWriters = setupResultsPersistence.StreamWriters.Length; for (var i = 0; i < numberOfDatas; i++) { foreach (string str in insertData.ToArray()[i]) { //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str); //ToDo: exception handling setupResultsPersistence.StreamWriters[i].WriteLine(str); } } return(new InsertViaFileResults(true)); }); Persistence <IInsertResultsAbstract> persistence = new Persistence <IInsertResultsAbstract>(insertFunc); #endregion #region PickAndSaveViaFiles setup // Ensure the Archived files are empty and can be written to // Call the SetupViaFileFuncBuilder here, execute the Func that comes back, with filePathsPickAndSave as the argument // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files ISetupViaFileResults setupResultsPickAndSave; try { setupResultsPickAndSave = PersistenceStaticExtensions.SetupViaFileFuncBuilder()(new SetupViaFileData(filePathsPickAndSave)); } catch (System.IO.IOException ex) { // prepare message for UI interface // ToDo: custom exception, and include its message here mesg.Append(uiLocalizer["IOException trying to setup PickAndSaveViaFiles"]); #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } mesg.Clear(); } #endregion // Throw exception, Cancel the entire service (internal CTS), or swallow and Continue (possibly offering hints as to resolution), client's choice throw ex; // internalCancellationTokenSource.Signal ???? // or just continue and let the user make another selection or go fix the problem //break; } // Create a pickFunc (AKA Predicate) var pickFuncPickAndSave = new Func <object, bool>((objToTest) => { return(FileIOExtensions.IsArchiveFile(objToTest.ToString()) || FileIOExtensions.IsMailFile(objToTest.ToString())); }); // Create an insert Func var insertFuncPickAndSave = new Func <IEnumerable <IEnumerable <object> >, IInsertViaFileResults>((insertData) => { int numberOfStreamWriters = setupResultsPickAndSave.StreamWriters.Length; for (var i = 0; i < numberOfStreamWriters; i++) { foreach (string str in insertData.ToArray()[i]) { //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str); //ToDo: exception handling // ToDo: Make formatting a parameter try { setupResultsPickAndSave.StreamWriters[i].WriteLine(str); } catch (System.IO.IOException ex) { throw; } } } return(new InsertViaFileResults(true)); }); PickAndSave <IInsertResultsAbstract> pickAndSave = new PickAndSave <IInsertResultsAbstract>(pickFuncPickAndSave, insertFuncPickAndSave); #endregion ConvertFileSystemToGraphResult convertFileSystemToGraphResult; #region Method timing setup Stopwatch stopWatch = new Stopwatch(); // ToDo: utilize a much more powerfull and ubiquitous timing and profiling tool than a stopwatch stopWatch.Start(); #endregion try { Func <Task <ConvertFileSystemToGraphResult> > run = () => ComputerInventoryHardwareStaticExtensions.ConvertFileSystemToGraphAsyncTask(rootString, asyncFileReadBlockSize, enableHash, convertFileSystemToGraphProgress, persistence, pickAndSave, linkedCancellationToken); convertFileSystemToGraphResult = await run.Invoke().ConfigureAwait(false); stopWatch.Stop(); // ToDo: utilize a much more powerfull and ubiquitous timing and profiling tool than a stopwatch // ToDo: put the results someplace } catch (Exception) { // ToDo: define explicit exceptions to catch and report upon // ToDo: catch FileIO.FileNotFound, sometimes the file disappears throw; } finally { // Dispose of the objects that need disposing setupResultsPickAndSave.Dispose(); setupResultsPersistence.Dispose(); } #region Build the results BuildConvertFileSystemToGraphResults(mesg, convertFileSystemToGraphResult, stopWatch); #endregion break; // case "2": // #region define the Func<string,Task> to be executed when the ConsoleSourceHostedService.ConsoleReadLineAsyncAsObservable produces a sequence element // // This Action closes over the current local variables' values // Func<string, Task> SimpleEchoToConsoleOutFunc = new Func<string, Task>(async (inputLineString) => { // #region Write the mesg to stdout // using (Task task = await WriteMessageSafelyAsync(inputLineString, consoleSinkHostedService, linkedCancellationToken).ConfigureAwait(false)) { // if (!task.IsCompletedSuccessfully) { // if (task.IsCanceled) { // // Ignore if user cancelled the operation during output to stdout (internal cancellation) // // re-throw if the cancellation request came from outside the stdInLineMonitorAction // /// ToDo: evaluate the linked, inner, and external tokens // throw new OperationCanceledException(); // } // else if (task.IsFaulted) { // //ToDo: Go through the inner exception // //foreach (var e in t.Exception) { // // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // // ToDo figure out what to do if the output stream is closed // throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); // //} // } // } // } // #endregion // }); // #endregion // break; // case "10": // #region setup a local block for handling this choice // try { // var enableHash = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnableHashBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnableHashBoolConfigRootKeyDefault)); // ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // var enableProgress = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnableProgressBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnableProgressBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // var enablePersistence = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnablePersistenceBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnablePersistenceBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // var enablePickAndSave = configurationRoot.GetValue<bool>(ConsoleMonitorStringConstants.EnablePickAndSaveBoolConfigRootKey, bool.Parse(ConsoleMonitorStringConstants.EnablePickAndSaveBoolDefault));// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // var dBConnectionString = configurationRoot.GetValue<string>(ConsoleMonitorStringConstants.DBConnectionStringConfigRootKey, ConsoleMonitorStringConstants.DBConnectionStringDefault);// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // // ToDo: This should be a string representation of a known enumeration of ORMLite DB providers that this service can support // var dBProvider = configurationRoot.GetValue<string>(ConsoleMonitorStringConstants.DBConnectionStringConfigRootKey, ConsoleMonitorStringConstants.DBConnectionStringDefault);// ToDo: should validate in case the ConsoleMonitorStringConstants assembly is messed up? // dBProvider = SqlServerOrmLiteDialectProvider.Instance; // #region ProgressReporting setup // ConvertFileSystemToGraphProgress? convertFileSystemToGraphProgress; // if (enableProgress) { // convertFileSystemToGraphProgress = new ConvertFileSystemToGraphProgress(); // } // else { // convertFileSystemToGraphProgress = null; // } // #endregion // #region PersistenceViaIORMSetup // // Call the SetupViaIORMFuncBuilder here, execute the Func that comes back, with dBConnectionString as the argument // // Ensure the NNode and Edge Tables for this PartitionInfo are empty and can be written to // // ToDo: create a function that will create Node and Edge tables if they don't yet exist, and use that function when creating the temp fiiles // // ToDo: add exception handling if the setup function fails // var setupResultsPersistence = PersistenceStaticExtensions.SetupViaORMFuncBuilder()(new SetupViaORMData(dBConnectionString, dBProvider, linkedCancellationToken)); // // Create an insertFunc that references the local variable setupResults, closing over it // var insertFunc = new Func<IEnumerable<IEnumerable<object>>, IInsertViaORMResults>((insertData) => { // int numberOfDatas = insertData.ToArray().Length; // int numberOfStreamWriters = setupResultsPersistence.StreamWriters.Length; // for (var i = 0; i < numberOfDatas; i++) { // foreach (string str in insertData.ToArray()[i]) { // //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str); // //ToDo: exception handling // setupResultsPersistence.Tables[i].SQLCmd(str); // } // } // return new InsertViaORMResults(true); // }); // Persistence<IInsertResultsAbstract> persistence = new Persistence<IInsertResultsAbstract>(insertFunc); // #endregion // #region PickAndSaveViaIORM setup // // Ensure the Node and Edge files are empty and can be written to // // Call the SetupViaIORMFuncBuilder here, execute the Func that comes back, with filePaths as the argument // // ToDo: create a function that will create subdirectories if needed to fulfill path, and use that function when creating the temp files // var setupResultsPickAndSave = PersistenceStaticExtensions.SetupViaORMFuncBuilder()(new SetupViaORMData(dBConnectionString, dBProvider, linkedCancellationToken)); // // Create a pickFunc // var pickFuncPickAndSave = new Func<object, bool>((objToTest) => { // return FileIOExtensions.IsArchiveFile(objToTest.ToString()) || FileIOExtensions.IsMailFile(objToTest.ToString()); // }); // // Create an insert Func // var insertFuncPickAndSave = new Func<IEnumerable<IEnumerable<object>>, IInsertViaORMResults>((insertData) => { // //int numberOfStreamWriters = setupResultsPickAndSave.StreamWriters.Length; // //for (var i = 0; i < numberOfStreamWriters; i++) { // // foreach (string str in insertData.ToArray()[i]) { // // //ToDo: add async versions await setupResults.StreamWriters[i].WriteLineAsync(str); // // //ToDo: exception handling // // // ToDo: Make formatting a parameter // // setupResultsPickAndSave.StreamWriters[i].WriteLine(str); // // } // //} // return new InsertViaORMResults(true); // }); // PickAndSave<IInsertResultsAbstract> pickAndSave = new PickAndSave<IInsertResultsAbstract>(pickFuncPickAndSave, insertFuncPickAndSave); // #endregion // } // // To Catch specific exceptions that might occur // catch { // } // // ToDo: dispose // finally { } // #endregion // break; case "99": #region Quit the program //internalcancellationtoken. #endregion break; default: mesg.Clear(); mesg.Append(uiLocalizer["InvalidInputDoesNotMatchAvailableChoices {0}", inputLine]); break; } #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } } #endregion #endregion #region Buildmenu await BuildMenu(); #endregion #region Write the mesg to stdout using (Task task = await WriteMessageSafelyAsync().ConfigureAwait(false)) { if (!task.IsCompletedSuccessfully) { if (task.IsCanceled) { // Ignore if user cancelled the operation during output to stdout (internal cancellation) // re-throw if the cancellation request came from outside the stdInLineMonitorAction /// ToDo: evaluate the linked, inner, and external tokens throw new OperationCanceledException(); } else if (task.IsFaulted) { //ToDo: Go through the inner exception //foreach (var e in t.Exception) { // https://docs.microsoft.com/en-us/dotnet/standard/io/handling-io-errors // ToDo figure out what to do if the output stream is closed throw new Exception("ToDo: WriteMessageSafelyAsync returned an AggregateException"); //} } } mesg.Clear(); } #endregion }