예제 #1
0
        /// <returns>Return true if cache is updated</returns>
        private bool CachePlugin(Plugin p, DB_PluginCache[] memDB, List <DB_PluginCache> updateDB)
        {
            if (memDB == null)
            {
                throw new ArgumentNullException("memDB");
            }

            // Does cache exist?
            FileInfo f     = new FileInfo(p.DirectFullPath);
            string   sPath = p.DirectFullPath.Remove(0, p.Project.BaseDir.Length + 1);

            bool updated = false;
            // int memIdx = 0;
            DB_PluginCache pCache = null;

            // Retrieve Cache
            pCache = memDB.FirstOrDefault(x => x.Hash == sPath.GetHashCode());

            // Update Cache into updateDB
            if (pCache == null)
            { // Cache not exists
                pCache = new DB_PluginCache()
                {
                    Hash             = sPath.GetHashCode(),
                    Path             = sPath,
                    LastWriteTimeUtc = f.LastWriteTimeUtc,
                    FileSize         = f.Length,
                };

                BinaryFormatter formatter = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    formatter.Serialize(ms, p);
                    pCache.Serialized = ms.ToArray();
                }

                listLock.EnterWriteLock();
                try
                {
                    updateDB.Add(pCache);
                    updated = true;
                }
                finally
                {
                    listLock.ExitWriteLock();
                }
            }
            else if (pCache.Path.Equals(sPath, StringComparison.Ordinal) &&
                     (DateTime.Equals(pCache.LastWriteTimeUtc, f.LastWriteTime) == false || pCache.FileSize != f.Length))
            { // Cache is outdated
                BinaryFormatter formatter = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    formatter.Serialize(ms, p);
                    pCache.Serialized       = ms.ToArray();
                    pCache.LastWriteTimeUtc = f.LastWriteTimeUtc;
                    pCache.FileSize         = f.Length;
                }

                listLock.EnterWriteLock();
                try
                {
                    updateDB.Add(pCache);
                    updated = true;
                }
                finally
                {
                    listLock.ExitWriteLock();
                }
            }

            if (p.Type == PluginType.Link && p.LinkLoaded)
            {
                bool linkUpdated = CachePlugin(p.Link, memDB, updateDB);
                updated = updated || linkUpdated;
            }

            return(updated);
        }
예제 #2
0
        private List <LogInfo> LoadLinks(BackgroundWorker worker)
        {
            List <LogInfo> logs       = new List <LogInfo>(32);
            List <int>     removeIdxs = new List <int>();

            // Doing this will consume memory, but also greatly increase performance.
            DB_PluginCache[] cacheDB = null;
            if (pluginCache != null)
            {
                cacheDB = pluginCache.Table <DB_PluginCache>().Where(x => true).ToArray();
            }

            var links = allProjectPlugins.Where(x => x.Type == PluginType.Link);

            Debug.Assert(links.Count(x => x.IsDirLink) == 0);
            Task[] tasks = links.Select(p =>
            {
                return(Task.Run(() =>
                {
                    Plugin link = null;
                    bool valid = false;
                    int cached = 2;
                    try
                    {
                        do
                        {
                            string linkPath = p.Sections["Main"].IniDict["Link"];
                            string linkFullPath = Path.Combine(baseDir, linkPath);
                            if (File.Exists(linkFullPath) == false) // Invalid link
                            {
                                break;
                            }

                            // Load .link's linked plugins with cache
                            if (pluginCache != null)
                            { // Case of PluginCache enabled
                                FileInfo f = new FileInfo(linkFullPath);
                                DB_PluginCache pCache = cacheDB.FirstOrDefault(x => x.Hash == linkPath.GetHashCode());
                                if (pCache != null &&
                                    pCache.Path.Equals(linkPath, StringComparison.Ordinal) &&
                                    DateTime.Equals(pCache.LastWriteTimeUtc, f.LastWriteTimeUtc) &&
                                    pCache.FileSize == f.Length)
                                {
                                    try
                                    {
                                        using (MemoryStream memStream = new MemoryStream(pCache.Serialized))
                                        {
                                            BinaryFormatter formatter = new BinaryFormatter();
                                            link = (Plugin)formatter.Deserialize(memStream);
                                        }
                                        link.Project = p.Project;
                                        link.IsDirLink = false;
                                        cached = 3;
                                    }
                                    catch { }
                                }
                            }

                            if (link == null)
                            {
                                // TODO : Lazy loading of link, takes too much time at start
                                string ext = Path.GetExtension(linkFullPath);
                                PluginType type = PluginType.Plugin;
                                if (ext.Equals(".link", StringComparison.OrdinalIgnoreCase))
                                {
                                    type = PluginType.Link;
                                }
                                link = new Plugin(type, Path.Combine(baseDir, linkFullPath), p.Project, projectRoot, null, false, false, false);

                                Debug.Assert(p != null);
                            }

                            // Check Plugin Link's validity
                            // Also, convert nested link to one-depth link
                            if (link == null)
                            {
                                break;
                            }

                            if (link.Type == PluginType.Plugin)
                            {
                                valid = true;
                                break;
                            }
                            link = link.Link;
                        }while (link.Type != PluginType.Plugin);
                    }
                    catch (Exception e)
                    { // Parser Error
                        logs.Add(new LogInfo(LogState.Error, Logger.LogExceptionMessage(e)));
                    }

                    if (valid)
                    {
                        p.LinkLoaded = true;
                        p.Link = link;
                        if (worker != null)
                        {
                            worker.ReportProgress(cached, Path.GetDirectoryName(p.ShortPath));
                        }
                    }
                    else // Error
                    {
                        int idx = allProjectPlugins.IndexOf(p);
                        removeIdxs.Add(idx);
                        if (worker != null)
                        {
                            worker.ReportProgress(cached);
                        }
                    }
                }));
            }).ToArray();
            Task.WaitAll(tasks);

            // Remove malformed link
            var idxs = removeIdxs.OrderByDescending(x => x);

            foreach (int idx in idxs)
            {
                allProjectPlugins.RemoveAt(idx);
            }

            return(logs);
        }