/// <summary> /// Deserializes into an instance of <see cref="VolumeMap"/>. /// </summary> public static VolumeMap Deserialize(BuildXLReader reader) { Contract.Requires(reader != null); var volumeMap = new VolumeMap(); int count = reader.ReadInt32Compact(); for (int i = 0; i < count; ++i) { ulong serialNumber = reader.ReadUInt64(); bool isValid = reader.ReadBoolean(); VolumeGuidPath path = isValid ? VolumeGuidPath.Create(reader.ReadString()) : VolumeGuidPath.Invalid; volumeMap.m_volumePathsBySerial.Add(serialNumber, path); } int numJunctionRoots = reader.ReadInt32Compact(); for (int i = 0; i < numJunctionRoots; ++i) { string path = reader.ReadString(); var id = FileIdAndVolumeId.Deserialize(reader); volumeMap.m_junctionRootFileIds.Add(path, id); } return(volumeMap); }
private static void ReadDictionary(BuildXLReader reader, Dictionary <string, FileIdAndVolumeId> dict) { int count = reader.ReadInt32Compact(); for (int i = 0; i < count; ++i) { string path = reader.ReadString(); var id = FileIdAndVolumeId.Deserialize(reader); dict.Add(path, id); } }
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)); } }