Ejemplo n.º 1
0
        public ConfigFileInfo TryHotload(ConfigFileInfo finfo)
        {
            var filename = m_baseDir + "/" + finfo.Name;

            filename = System.IO.Path.ChangeExtension(filename, null);
            TextAsset asset = (TextAsset)Resources.Load(filename);

            if (asset == null)
            {
                Config.Log(LogVerbosity.Error, "Null when loading file", filename);
                return(null);
            }
            var contents = asset.text;
            var checksum = ConfigFileManager.Checksum(contents);

            if (checksum == finfo.Checksum)
            {
                // early-out with a false result
                return(null);
            }

            var parsed = Config.LoadDocFromString(contents, finfo.Name);

            return(new ConfigFileInfo {
                Name = finfo.Name,
                Size = contents.Length,
                Checksum = checksum,
                Parsed = parsed
            });
        }
Ejemplo n.º 2
0
        public void HotloadIndex(ConfigFileInfo indexInfo)
        {
            if (m_index == null)
            {
                Config.Log(LogVerbosity.Warn, "Null m_index");
                return;
            }

            var indexNode = indexInfo.Parsed;

            var newFiles     = new List <string>(10);
            var removedFiles = new List <string>(10);

            for (int i = 0; i < indexNode.Count; i++)
            {
                var fname = indexNode[i].StringValue;
                if (!m_index.Contains(fname))
                {
                    newFiles.Add(fname);
                }
            }
            for (int i = 0; i < m_index.Count; i++)
            {
                if (!indexNode.Contains(m_index[i]))
                {
                    removedFiles.Add(m_index[i]);
                }
            }

            for (int i = 0; i < newFiles.Count; i++)
            {
                var filename = newFiles[i];
                m_index.Add(filename);
                if (filename == "index")
                {
                    continue;
                }
                try {
                    var finfo = ReadFile(m_baseDir + "/" + filename, filename);
                    m_files.Add(finfo);
                } catch (Exception) {
                    continue;
                }
            }

            for (int i = 0; i < removedFiles.Count; i++)
            {
                m_index.Remove(removedFiles[i]);
                for (int j = 0; j < m_files.Count; j++)
                {
                    if (m_files[j].Name == removedFiles[i])
                    {
                        m_files.RemoveAt(j);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        void CallCallbacks(List <string> modifiedFiles)
        {
            // generate any combined files once, then mark that file changed
            for (int i = 0; i < modifiedFiles.Count; i++)
            {
                var filename = modifiedFiles[i];

                if (m_combinersBySubfile.ContainsKey(filename))
                {
                    var multicallbacks = m_combinersBySubfile[filename];
                    for (int j = 0; j < multicallbacks.Count; j++)
                    {
                        var mc        = multicallbacks[j];
                        var shortName = mc.DestinationFilename;
                        m_loadedFiles[shortName] = new ConfigFileInfo {
                            Name   = shortName,
                            Parsed = BuildCombinedConfig(mc.DestinationFilename)
                        };
                        modifiedFiles.Add(mc.DestinationFilename);
                    }
                }
            }

            // call callbacks for modified files
            for (int i = 0; i < modifiedFiles.Count; i++)
            {
                var filename = modifiedFiles[i];
                if (!m_reloadCallbacks.ContainsKey(filename))
                {
                    continue;
                }
                var callbacks = m_reloadCallbacks[filename];
                for (int j = 0; j < callbacks.Count; j++)
                {
                    var doc  = LoadConfig(filename);
                    var save = callbacks[j](doc);
                    if (!save)
                    {
                        callbacks.RemoveAt(j);
                        j--;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Create a "combined file", which is made up of the contents of several other files.
        /// It's not actually a real file, it's only in-memory, but you can load this combined
        /// file as though it was a real file in the index.  Useful as a technique to manage a
        /// directory of small config files as though it's one big file, or even more esoteric stuff.
        /// </summary>
        /// <param name="sourceFilenames">List of filenames that are to be combined</param>
        /// <param name="newFilename">Name of the new combined file.  Once it's registered,
        /// you call LoadConfig with this name.  Should be unique -- naming a combined file
        /// the same as another will clobber it.</param>
        /// <param name="combiner">Function that takes in an array of DocNodes and returns a
        /// DocNode.  Implement whatever algorithm you want.  This function gets called every
        /// time any of the source files changes, with the DocNodes of all source files.</param>
        public void RegisterCombinedFile(List <string> sourceFilenames, string newFilename, System.Func <List <DocNode>, DocNode> combiner)
        {
            CheckPreload();

            // clobber any existing setup for this filename
            if (m_combiners.ContainsKey(newFilename))
            {
                UnregisterCombinedFile(newFilename);
            }

            var listener = new CombinerData {
                Filenames           = sourceFilenames.ToArray(),
                Combiner            = combiner,
                DestinationFilename = newFilename
            };

            m_combiners[newFilename] = listener;
            for (int i = 0; i < sourceFilenames.Count; i++)
            {
                var filename = sourceFilenames[i];
                if (!m_combinersBySubfile.ContainsKey(filename))
                {
                    m_combinersBySubfile[filename] = new List <CombinerData>();
                }
                var list = m_combinersBySubfile[sourceFilenames[i]];
                if (!list.Contains(listener))
                {
                    list.Add(listener);
                }
            }

            if (m_isPreloaded)
            {
                m_loadedFiles[newFilename] = new ConfigFileInfo {
                    Name   = newFilename,
                    Parsed = BuildCombinedConfig(newFilename)
                };
            }
        }
Ejemplo n.º 5
0
        internal ConfigFileInfo CheckHotload(string configName)
        {
            ConfigFileInfo finfo = null;

            lock (m_loadedFiles) {
                finfo = m_loadedFiles[configName];
            }

            for (int i = 0; i < m_sources.Count; i++)
            {
                var source = m_sources[i];
                if (!source.CanHotload())
                {
                    continue;
                }

                var newInfo = source.TryHotload(finfo);

                if (newInfo != null)
                {
                    Config.Log(LogVerbosity.Info, "Hotloaded file " + newInfo + " old: " + finfo);

                    if (newInfo.Name == "index")
                    {
                        // make sure that we sync up our list of loaded files
                        HotloadIndex(source);
                    }
                    if (OnHotloadFile != null)
                    {
                        OnHotloadFile(newInfo.Name);
                    }
                    return(newInfo);
                }
            }
            return(null);
        }
Ejemplo n.º 6
0
        public ConfigFileInfo TryHotload(ConfigFileInfo finfo)
        {
            var filename = m_baseDir + "/" + finfo.Name + ".bytes";

            if (!File.Exists(filename))
            {
                return(null);
            }
            var systemInfo   = new System.IO.FileInfo(filename);
            var modifiedTime = File.GetLastWriteTimeUtc(filename);
            var fileLength   = systemInfo.Length;

            if (fileLength == finfo.Size && AreTimestampsEquivalent(modifiedTime, finfo.Modified))
            {
                return(null);
            }

            // size and modified time differ; have to open the whole file to see if it's actually different
            using (var fileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
                var size     = (int)fileStream.Length;
                var checksum = ConfigFileManager.Checksum(fileStream);
                if (checksum == finfo.Checksum)
                {
                    if (!AreTimestampsEquivalent(modifiedTime, finfo.Modified))
                    {
                        // set the mtime on the file so that we don't have to re-check it later
                        Config.Log(LogVerbosity.Info, "Setting mtime on file", finfo, "prev", modifiedTime, "new", finfo.Modified);
                        try {
                            File.SetLastWriteTimeUtc(filename, finfo.Modified);
                        } catch (Exception e) {
                            Config.Log(LogVerbosity.Info, "Error setting mtime on file", finfo, e.ToString());
                            // if we can't modify the file then let's at least store the mtime in memory for next time
                            finfo.Modified = modifiedTime;
                        }
                    }

                    if (fileLength != finfo.Size)
                    {
                        // for some reason the file's length is different, but the checksum is the same, so let's remember the size so next time we won't have to reload
                        Config.Log(LogVerbosity.Info, "Saving size of file", finfo, "prev", finfo.Size, "new", fileLength);
                        finfo.Size = (int)fileLength;
                    }

                    return(null); // checksum same, can skip parsing/hotloading this file
                }

                fileStream.Seek(0, SeekOrigin.Begin);

                var parsed = Config.LoadDocFromStream(fileStream, finfo.Name);

                var newInfo = new ConfigFileInfo {
                    Name     = finfo.Name,
                    Size     = size,
                    Modified = modifiedTime,
                    Checksum = checksum,
                    Parsed   = parsed
                };
                if (newInfo.Name == "index")
                {
                    HotloadIndex(newInfo);  // index loading should trigger loading other files
                }
                return(newInfo);
            }
        }