Exemple #1
0
        /// <summary>
        /// Adapts the specified experiment into runnable experiment.
        /// Adapt method validates given experiment and builds runnable experiment which is going to be executed by the experiment runner.
        /// During adapation the experiment is validated.
        /// In case of detected error in the experiment, this method returns empty RunnableExperimentBase with no nodes and no edges.
        /// There are several errors that can be detected.
        /// There are nodes connected to start, but not to graph end.
        /// Loops without decisions nodes.
        /// Input mappings are incorrect.
        /// Failed component load or instantiation, especially in case of incorrect configuration values.
        /// </summary>
        /// <param name="experiment">The experiment which is going to be adapted into RunnableExperiment..</param>
        /// <param name="nodesFactory">The nodes factory, by which all nodes in runnable experiment are created..</param>
        /// <param name="library">The library of components.</param>
        /// <param name="workspaceTypeDirectories">The workspace type directories.</param>
        /// <returns>
        /// Runnable experiment that experiment is going to execute, pruned from nodes that are not connected to main flow beginning at Start node.
        /// In case of detected error in the experiment, this method returns empty RunnableExperimentBase with no nodes and no edges.
        /// </returns>
        public static RunnableExperimentBase Adapt(IExperiment experiment, IRunnableNodeFactory nodesFactory, Components.ComponentsLibrary library, List <string> workspaceTypeDirectories)
        {
            LoggerNameRoot loggerNameRoot = new LoggerNameRoot(experiment.ExperimentInfo.Id);

            // Create the new domain for the runnable experiment with whatever current security evidence we're running with.
            // The components app domain is the app domain which components assemblies are going to be loaded into.

            var       helper = new TraceLab.Core.Components.LibraryHelper(workspaceTypeDirectories);
            AppDomain componentsAppDomain = helper.CreateDomain(experiment.ExperimentInfo.Id);

            return(Adapt(experiment, loggerNameRoot, nodesFactory, library, workspaceTypeDirectories, componentsAppDomain, new System.Threading.ManualResetEvent(false), true));
        }
        /// <summary>
        /// Adapts the specified experiment into runnable experiment.
        /// Adapt method validates given experiment and builds runnable experiment which is going to be executed by the experiment runner.
        /// During adapation the experiment is validated.
        /// In case of detected error in the experiment, this method returns empty RunnableExperimentBase with no nodes and no edges.
        /// There are several errors that can be detected.
        /// There are nodes connected to start, but not to graph end.
        /// Loops without decisions nodes.
        /// Input mappings are incorrect.
        /// Failed component load or instantiation, especially in case of incorrect configuration values.
        /// </summary>
        /// <param name="experiment">The experiment which is going to be adapted into RunnableExperiment..</param>
        /// <param name="nodesFactory">The nodes factory, by which all nodes in runnable experiment are created..</param>
        /// <param name="library">The library of components.</param>
        /// <param name="workspaceTypeDirectories">The workspace type directories.</param>
        /// <returns>
        /// Runnable experiment that experiment is going to execute, pruned from nodes that are not connected to main flow beginning at Start node. 
        /// In case of detected error in the experiment, this method returns empty RunnableExperimentBase with no nodes and no edges.
        /// </returns>
        public static RunnableExperimentBase Adapt(IExperiment experiment, IRunnableNodeFactory nodesFactory, Components.ComponentsLibrary library, List<string> workspaceTypeDirectories)
        {
            LoggerNameRoot loggerNameRoot = new LoggerNameRoot(experiment.ExperimentInfo.Id);

            // Create the new domain for the runnable experiment with whatever current security evidence we're running with.
            // The components app domain is the app domain which components assemblies are going to be loaded into.

            var helper = new TraceLab.Core.Components.LibraryHelper(workspaceTypeDirectories);
            AppDomain componentsAppDomain = helper.CreateDomain(experiment.ExperimentInfo.Id);

            return Adapt(experiment, loggerNameRoot, nodesFactory, library, workspaceTypeDirectories, componentsAppDomain, new System.Threading.ManualResetEvent(false), true);
        }
Exemple #3
0
        /// <summary>
        /// Scans the specified directories for components not already present in cache.
        /// </summary>
        /// <param name="directories">The directories.</param>
        /// <param name="workspaceTypeDirectories">The workspace type directories.</param>
        /// <param name="cachedFiles">Components already loaded in the cache.</param>
        /// <param name="results">.</param>
        /// <returns>
        /// True or False depending on the success of the scanning operation.
        /// </returns>
        public static bool Scan(IEnumerable<string> directories, IEnumerable<string> workspaceTypeDirectories,
            ISet<string> cachedFiles, ComponentScanResults results)
        {
            bool success = true;

            AppDomain newDomain = null;

            try
            {
                var libraryHelper = new LibraryHelper(workspaceTypeDirectories);

                newDomain = libraryHelper.CreateDomain("ComponentScanner", false);
                newDomain.Load(Assembly.GetExecutingAssembly().GetName());

                // Preload the workspace types so that the component scanner won't barf when a component references a workspace type.
                libraryHelper.PreloadWorkspaceTypes(newDomain);

                ComponentScanner scanner = (ComponentScanner)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(ComponentScanner).FullName, false, BindingFlags.Instance | BindingFlags.NonPublic, null, null, null, null);

                if (!RuntimeInfo.IsRunInMono)
                {
                    scanner.Scan(directories, cachedFiles);
                }
                else
                {
                    scanner.Scan(directories, new List<string>(cachedFiles));
                }

                results.NewFilesLoaded = new List<FileDescriptor>(scanner.NewFilesLoaded);
                results.RequestedFiles = new List<string>(scanner.FilesToGetFromCache);

                results.Errors = new List<string>(scanner.Errors);
            }
            catch (Exception e)
            {
                success = false;

                results.NewFilesLoaded = new List<FileDescriptor>();
                results.RequestedFiles = new List<string>();
                results.OldGuidToNewGuidMap = new Dictionary<string, string>();

                results.Errors = results.Errors ?? new List<string>();
                results.Errors.Add(e.Message);
            }
            finally
            {
                if (newDomain != null)
                {
#if !MONO_DEV
                    //appdomain unload crashes mono.exe process when running directly from 
                    //Mono Develop, possibly because attached debugger. When run normally works fine.
                    //use MONO_DEV compiler symbol when developing
                    AppDomain.Unload(newDomain);
#endif
                }
            }

            return success;
        }
        /// <summary>
        /// Builds the source of decision module and compile decision module into the assembly
        /// </summary>
        /// <param name="metadata">The metadata.</param>
        /// <param name="successorNodeLabelIdLookup">The successor node label id lookup.</param>
        /// <param name="predeccessorsOutputsNameTypeLookup">The predeccessors outputs name type lookup.</param>
        /// <param name="workspaceTypesDirectories">The workspace types directories.</param>
        /// <param name="loggerNameRoot">The logger name root.</param>
        private static void BuildSourceAndCompileDecisionModule(IDecision metadata, Dictionary<string, string> successorNodeLabelIdLookup,
                                            Dictionary<string, string> predeccessorsOutputsNameTypeLookup, 
                                            List<string> workspaceTypesDirectories, LoggerNameRoot loggerNameRoot)
        {
            metadata.FireRequestLatestCode();

            //create local componentlogger (ComponentLoggerImplementation implements MarshalByRefObject, thanks to which it can pass logs between appdomains
            TraceLabSDK.ComponentLogger logger = LoggerFactory.CreateLogger(loggerNameRoot, metadata.UniqueDecisionID, metadata);

            //construct the final code, and collect types assemblies locations to be referenced by the compilator
            HashSet<string> assembliesReferenceLocations;
            string finalDecisionModuleSourceCode = DecisionCodeBuilder.BuildCodeSource(metadata, workspaceTypesDirectories, 
                                successorNodeLabelIdLookup, predeccessorsOutputsNameTypeLookup, logger, out assembliesReferenceLocations);

            // Create the new domain with whatever current security evidence we're running with using the library helper
            LibraryHelper helper = new LibraryHelper(workspaceTypesDirectories);

            AppDomain newDomain = helper.CreateDomain("DecisionModuleCompilation");
            newDomain.Load(Assembly.GetExecutingAssembly().GetName());
            helper.PreloadWorkspaceTypes(newDomain);

            //// Load our output assembly into the other domain.
            DecisionModuleCompilator compiler =
                (DecisionModuleCompilator)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(DecisionModuleCompilator).FullName,
                                                                            false,
                                                                            BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance, null,
                                                                            new object[] { },
                                                                            System.Globalization.CultureInfo.CurrentCulture, new object[] { });
            
            compiler.CompileDecisionModule(finalDecisionModuleSourceCode, metadata.SourceAssembly, assembliesReferenceLocations);

#if !MONO_DEV
            //when developing on mono in MonoDevelop application crashes when unloading appdomain.
            //it only happens from within of MonoDevelop with attached debugger. Running normally, works fine.
            AppDomain.Unload(newDomain);
#endif
        }