/// <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); }
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)); } }