示例#1
0
        /// <summary>
        ///     Constructor.
        /// </summary>
        /// <param name="indexFile"></param>
        /// <param name="dataFile"></param>
        protected void Initialize(String indexFile, String dataFile)
        {
            logger.Trace("Cache index file: {0}", indexFile);
            logger.Trace("Cache data file: {0}", dataFile);

            // Open cache files if BOTH index and data files exist
            if (File.Exists(indexFile) && File.Exists(dataFile))
            {
                try
                {
                    logger.Info("Cache files found, attempting to load.");

                    // Open cache files
                    indexStream = new StreamEx(indexFile);
                    dataStream  = new StreamEx(dataFile);

                    // Load index file
                    string magicNumber = new String(Encoding.ASCII.GetChars(indexStream.ReadBytes(0x10)));
                    if (magicNumber.Equals(MagicNumber))
                    {
                        // Calculate the entry count
                        long entryCount = (indexStream.Length - MagicNumber.Length) / IndexAlignment;

                        // Load Data
                        for (int i = 0; i < entryCount; i++)
                        {
                            // Load Address and length
                            long address = indexStream.ReadInt64();
                            long length  = indexStream.ReadInt64();

                            // Entry is valid only if address is greater or equal than 0
                            if (address >= 0)
                            {
                                // Read Name
                                string name =
                                    new String(Encoding.UTF8.GetChars(indexStream.ReadBytes(IndexAlignment - 0x10)));
                                name = name.TrimEnd('\0');

                                // Add Entry
                                CacheEntry entry = new CacheEntry
                                {
                                    Address         = address,
                                    Length          = length,
                                    MetadataAddress = i * IndexAlignment + MagicNumber.Length,
                                    Name            = name
                                };
                                entriesMap.Add(entry.Name, entry.Address);
                                entries.Add(entry.Address, entry);
                            }
                            else
                            {
                                // Add the unused entry to the holes
                                indexHoles.Enqueue(i * IndexAlignment + MagicNumber.Length);
                            }
                        }

                        // Scan for data holes
                        //var sortedEntries = entries.Values.OrderBy(t => t.Address).ToArray();
                        CacheEntry[] sortedEntries = entries.Values.ToArray(); // <-- this should be sorted correctly
                        for (int i = 0; i < entries.Count - 1; i++)
                        {
                            long lastEntryEnd   = Align(sortedEntries[i].EndAddress, DataAlignment);
                            long nextEntryStart = sortedEntries[i + 1].Address;
                            long holeSize       = nextEntryStart - lastEntryEnd;

                            // Positive hole size means a data hole, negative means corrupted data
                            if (holeSize > 0)
                            {
                                dataHoles.Add(lastEntryEnd, holeSize);
                            }
                            else if (holeSize < 0)
                            {
                                throw new InvalidDataException("Negative hole (overlapping data) detected.");
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidDataException("Invalid magic number!");
                    }
                }
                catch (Exception x)
                {
                    logger.Warn("Cache file corrupted: [{0}] {1}", x.GetType().FullName, x.Message);
                    indexStream.Dispose();
                    dataStream.Dispose();
                    indexStream = null;
                    dataStream  = null;
                }
            }
            else
            {
                logger.Info("Cache index or data file not found, proceeding to creating empty cache.");
            }

            if (indexStream == null && dataStream == null)
            {
                // Overwrite BOTH index and data files if one of them is missing
                // This is also the fallback route if cache files are corrupted
                indexStream = new StreamEx(indexFile, FileMode.Create);
                indexStream.WriteBytes(Encoding.ASCII.GetBytes(MagicNumber));
                dataStream = new StreamEx(dataFile, FileMode.Create);
            }
        }