예제 #1
0
            /// <summary>
            /// Deserializes
            /// </summary>
            public static FileLocation Deserialize(BuildXLReader reader)
            {
                FileLocation result = default(FileLocation);

                result.Path   = reader.ReadString();
                result.Hash   = ContentHashingUtilities.CreateFrom(reader);
                result.Length = reader.ReadInt32Compact();
                result.Offset = reader.ReadInt64Compact();

                return(result);
            }
예제 #2
0
        private static LoadResult TryLoadInternal(string fileContentTablePath, byte entryTimeToLive)
        {
            Contract.Requires(!string.IsNullOrWhiteSpace(fileContentTablePath));
            Contract.Requires(entryTimeToLive > 0);

            if (!FileUtilities.FileExistsNoFollow(fileContentTablePath))
            {
                return(LoadResult.FileNotFound(fileContentTablePath));
            }

            Stopwatch sw = Stopwatch.StartNew();

            try
            {
                using (FileStream stream = FileUtilities.CreateFileStream(
                           fileContentTablePath,
                           FileMode.Open,
                           FileAccess.Read,
                           FileShare.Read | FileShare.Delete,
                           // Ok to evict the file from standby since the file will be overwritten and never reread from disk after this point.
                           FileOptions.SequentialScan))
                {
                    try
                    {
                        Analysis.IgnoreResult(s_fileEnvelope.ReadHeader(stream));
                    }
                    catch (BuildXLException ex)
                    {
                        return(LoadResult.InvalidFormat(fileContentTablePath, ex.LogEventMessage, sw.ElapsedMilliseconds));
                    }

                    using (var reader = new BuildXLReader(debug: false, stream: stream, leaveOpen: true))
                    {
                        var loadedTable = new FileContentTable();

                        uint numberOfEntries = reader.ReadUInt32();
                        int  hashLength      = ContentHashingUtilities.HashInfo.ByteLength;
                        var  hashBuffer      = new byte[hashLength];

                        for (uint i = 0; i < numberOfEntries; i++)
                        {
                            // Key: Volume and file ID
                            var fileIdAndVolumeId = FileIdAndVolumeId.Deserialize(reader);

                            // Entry: USN, hash, length, time to live.
                            Usn usn = new Usn(reader.ReadUInt64());

                            int hashBytesRead = 0;
                            while (hashBytesRead != hashLength)
                            {
                                int thisRead = reader.Read(hashBuffer, hashBytesRead, hashLength - hashBytesRead);
                                if (thisRead == 0)
                                {
                                    return(LoadResult.InvalidFormat(fileContentTablePath, "Unexpected end of stream", sw.ElapsedMilliseconds));
                                }

                                hashBytesRead += thisRead;
                                Contract.Assert(hashBytesRead <= hashLength);
                            }

                            long length = reader.ReadInt64();

                            byte thisEntryTimeToLive = reader.ReadByte();
                            if (thisEntryTimeToLive == 0)
                            {
                                return(LoadResult.InvalidFormat(fileContentTablePath, "TTL value must be positive", sw.ElapsedMilliseconds));
                            }

                            thisEntryTimeToLive = Math.Min(thisEntryTimeToLive, entryTimeToLive);
                            Contract.Assert(thisEntryTimeToLive > 0);

                            // We've loaded this entry just now and so clearly haven't used it yet. Tentatively decrement the TTL
                            // for the in-memory table; if the table is saved again without using this entry, the TTL will stay at this
                            // lower value.
                            thisEntryTimeToLive--;

                            var  observedVersionAndHash = new Entry(usn, ContentHashingUtilities.CreateFrom(hashBuffer), length, thisEntryTimeToLive);
                            bool added = loadedTable.m_entries.TryAdd(fileIdAndVolumeId, observedVersionAndHash);
                            Contract.Assume(added);
                        }

                        loadedTable.Counters.AddToCounter(FileContentTableCounters.NumEntries, loadedTable.Count);

                        return(LoadResult.Success(fileContentTablePath, loadedTable, sw.ElapsedMilliseconds));
                    }
                }
            }
            catch (Exception ex)
            {
                return(LoadResult.Exception(fileContentTablePath, ex, sw.ElapsedMilliseconds));
            }
        }