Ejemplo n.º 1
0
        // DataContext creates plugins
        internal Plugin(DataContext context, string fileName, PluginMode mode)
        {
            this.context = context;
            this.fileName = fileName;

            if (mode == PluginMode.Create)
            {
                header = context.CreateHeader();
                header.NextFormId = 0x800;
            }
            else if (mode == PluginMode.Open)
            {
                // Read only the header mainly to fetch the list of masters
                Stream stream = context.DataFileProvider.GetDataFile(FileMode.Open, fileName).Open();
                using (var reader = context.CreateReader(stream))
                {
                    header = reader.ReadHeader();
                }
            }
            else
            {
                throw new ArgumentException("Illegal plugin mode specified");
            }
        }
Ejemplo n.º 2
0
        public void Load()
        {
            Log.Info("Indexing forms in plugin {0}", fileName);

            Stream stream = context.DataFileProvider.GetDataFile(FileMode.Open, fileName).Open();
            using (var reader = context.CreateReader(stream))
            {
                // Header needs to be read again
                header = reader.ReadHeader();

                // Prepare reference mapper
                reader.ReferenceMapper = new PluginReferenceMapper(this);

                int before = context.Forms.Count();
                int overriding = 0;
                int added = 0;

                using (var progress = Display.StartProgress("Indexing forms"))
                {

                    if (context.AsyncFormIndexing)
                    {
                        // Retrieve plugin number so that loaded forms can be linked to it
                        byte pluginNumber = context.Plugins.GetPluginNumber(this);

                        foreach (var record in reader.FindRecordsAsync())
                        {
                            Form form = new Form()
                            {
                                PluginNumber = pluginNumber,
                                FilePosition = record.FilePosition,
                                FormKind = (FormKind)record.Signature,
                                FormId = reader.ReferenceMapper.LocalToContext(record.FormId),
                                ParentFormId = reader.ReferenceMapper.LocalToContext(record.ParentRecordFormId)
                            };

                            // Index loaded form
                            context.Forms.Add(form);

                            added++;
                            if (form.IsOverriding)
                                overriding++;

                            progress.Update(reader.TotalRecordsFound, header.NumRecords, "{0} ({1})", fileName, form.FormKind);
                        }
                    }
                    else
                    {
                        FindRecordsListener listener = new FindRecordsListener(this, reader, progress);
                        reader.FindRecords(listener);
                        added = listener.Added;
                        overriding = listener.Overriding;
                    }
                }

                Log.Info("Found {0} forms ({1} overrides)", added, overriding);

                //if (header.NumRecords != reader.TotalRecordsFound)
                //{
                //    Log.Warning("Number of records specified in header {0} does not match number of records found {1}", header.NumRecords, reader.TotalRecordsFound);
                //}
            }
        }
Ejemplo n.º 3
0
        public void LoadForms(bool lazyLoading, Func<Form, bool> predicate)
        {
            if (context.AsyncFromLoadingMaxWorkers < 1)
                throw new InvalidOperationException("AsyncFromLoadingMaxWorkers cannot be less than 1");

            Stream stream = context.DataFileProvider.GetDataFile(FileMode.Open, fileName).Open();

            // Uncomment this to preload a whole file into memory
            // The loading time is marginaly shorter (around 4%)
            // but only when another background worker is employed
            //Log.Fine("Preloading plugin file {0}.", fileName);
            //var data = new byte[stream.Length];
            //stream.Read(data, 0, (int)stream.Length);
            //stream = new ReadOnlyMemoryStream(data);

            using (var reader = context.CreateReader(stream))
            {
                // Header needs to be read again
                header = reader.ReadHeader();

                // Prepare reference mapper
                reader.ReferenceMapper = new PluginReferenceMapper(this);

                // Prepare string locator (if plugin strings are localized)
                if (reader.PluginFlags.HasFlag(PluginFlags.Localized))
                    reader.StringLocator = new PluginStringLocator(this);

                int formsToLoadCount = 0;

                // Apply predicate to the enumeration, if any
                // this will cause the total number of forms to load be unknown
                var formsToLoadEnumeration = context.Forms.OfPlugin(this);
                if (predicate != null)
                {
                    // TODO: Fix the list to make the total count known
                    formsToLoadEnumeration = formsToLoadEnumeration.Where(predicate);
                    formsToLoadCount = formsToLoadEnumeration.Count();
                }
                else
                {
                    // Get count if enumeration is a list or a collection
                    formsToLoadCount = formsToLoadEnumeration.Count();
                }

                if (formsToLoadEnumeration.Any())
                {
                    var formsToLoad = formsToLoadEnumeration;
                    int formsToLoadCountAtLeast = 0;

                    // Determine number of background jobs, if any
                    int jobs = 0;
                    if (context.AsyncFormLoading)
                    {
                        // Materialize part of the list
                        // to determine the count of background jobs at least
                        if (formsToLoadCount == 0)
                        {
                            int take = context.AsyncFormLoadingWorkerThreshold * context.AsyncFromLoadingMaxWorkers;
                            formsToLoadCountAtLeast = formsToLoad.Take(take).Count();
                            if (formsToLoadCountAtLeast < take)
                                formsToLoadCount = formsToLoadCountAtLeast;
                        }

                        // Determine number of jobs
                        if (formsToLoadCount > 0)
                        {
                            // Use known number of forms to load
                            jobs = Math.Min(formsToLoadCount / context.AsyncFormLoadingWorkerThreshold + 1, context.AsyncFromLoadingMaxWorkers);
                        }
                        else
                        {
                            // Use minimal determined number of forms to load
                            jobs = Math.Min(formsToLoadCountAtLeast / context.AsyncFormLoadingWorkerThreshold + 1, context.AsyncFromLoadingMaxWorkers);
                        }
                    }

                    // Indicate that total number of forms to load will be determined during iteration
                    bool formsToLoadIsUnknown = formsToLoadCount == 0;

                    if (formsToLoadIsUnknown)
                    {
                        Log.Fine("Total number of forms to load is not unknown");
                        if (context.AsyncFormLoading)
                        {
                            Log.Fine("Using {0} background jobs to load more than {1} forms", jobs, formsToLoadCountAtLeast);
                        }
                    }
                    else if (context.AsyncFormLoading)
                    {
                        Log.Fine("Using {0} background jobs to load {1} forms", jobs, formsToLoadCount);
                    }

                    using (var loader = new FormLoader(this, reader, lazyLoading, jobs))
                    {
                        using (var progress = Display.StartProgress("Loading forms"))
                        {
                            foreach (Form form in formsToLoad)
                            {
                                // Do not load froms which have been injected during indexing
                                if (!form.IsInjected && !form.IsHardcoded)
                                {
                                    loader.LoadForm(form);
                                }

                                // Unknown total number of forms to load
                                // has to be determined during iteration
                                if (formsToLoadIsUnknown)
                                    formsToLoadCount++;

                                var lastFormLoaded = loader.LastFormLoaded;
                                progress.Update(loader.Loaded, Math.Max(formsToLoadCount, formsToLoadCountAtLeast),
                                    "{0} {1}", fileName, lastFormLoaded == null ? string.Empty : lastFormLoaded.ToString());
                            }

                            if (context.AsyncFormLoading)
                            {
                                // Tell loader no more forms will be loaded
                                loader.Complete();

                                // Show progress while loader is still busy
                                while (loader.IsBusy)
                                {
                                    System.Threading.Thread.Sleep(30);
                                    var lastFormLoaded = loader.LastFormLoaded;
                                    progress.Update(loader.Loaded, Math.Max(formsToLoadCount, formsToLoadCountAtLeast),
                                        "{0} {1}", fileName, lastFormLoaded == null ? string.Empty : lastFormLoaded.ToString());
                                }

                                // Wait for loader to finish completely
                                Log.Fine("Waiting for background jobs to finish");
                                loader.WaitForCompleted();
                            }
                        }

                        Log.Info("Loaded {0} forms from {1} ({2} supported, {3} unsupported)", loader.Loaded, fileName, loader.Supported, loader.Unsupported);

                        if (loader.Skipped > 0)
                            Log.Info("Skipped {0} forms that had been already loaded", loader.Skipped);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        internal void WriteHeader(HeaderRecord header)
        {
            if (this.header != null)
                throw new InvalidOperationException("Header already written");

            this.header = header;

            DoWriteRecord(header, 0);
        }