private static FileSystemType GetFileSystemType(string path) { using (FileStream fileStream = FileUtilities.CreateFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { return(FileUtilities.GetVolumeFileSystemByHandle(fileStream.SafeFileHandle)); } }
private static bool SupportCopyOnWrite(string path) { using (FileStream fileStream = FileUtilities.CreateFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { return(FileUtilities.CheckIfVolumeSupportsCopyOnWriteByHandle(fileStream.SafeFileHandle)); } }
public void TestVolumeFileSystemName() { var file = GetFullPath(nameof(TestVolumeFileSystemName)); File.WriteAllText(file, nameof(TestVolumeFileSystemName)); using (var stream = FileUtilities.CreateFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { FileSystemType fsType = FileUtilities.GetVolumeFileSystemByHandle(stream.SafeFileHandle); XAssert.AreNotEqual(FileSystemType.Unknown, fsType); } }
/// <summary> /// Retrieves an already-known <see cref="ContentHash" /> for the given path. If no such hash is available (such as if the /// file has been modified since a hash was last recorded), null is returned instead. /// </summary> /// <remarks> /// Note that this results in a small amount of I/O (e.g., on Windows, a file open and USN query), but never hashes the file or reads its contents. /// </remarks> /// <exception cref="BuildXLException">Thrown if the given path could not be opened for reading.</exception> public VersionedFileIdentityAndContentInfo?TryGetKnownContentHash(string path) { Contract.Requires(!string.IsNullOrWhiteSpace(path)); try { using ( FileStream stream = FileUtilities.CreateFileStream( path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { return(TryGetKnownContentHash(stream.Name, stream.SafeFileHandle)); } } catch (BuildXLException) { return(null); } }
private static void WithNewFileMemoryMapped(string path, Action action) { using (FileStream file = FileUtilities.CreateFileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete | FileShare.Read)) { file.SetLength(1024); using ( MemoryMappedFile.CreateFromFile( file, mapName: null, capacity: 0, access: MemoryMappedFileAccess.ReadWrite, #if !DISABLE_FEATURE_MEMORYMAP_SECURITY memoryMappedFileSecurity: null, #endif inheritability: HandleInheritability.None, leaveOpen: false)) { action(); } } }
private void SaveInternal(string fileContentTablePath) { Contract.Requires(!string.IsNullOrWhiteSpace(fileContentTablePath)); Contract.EnsuresOnThrow <BuildXLException>(true); ExceptionUtilities.HandleRecoverableIOException( () => { int numEvicted = 0; Directory.CreateDirectory(Path.GetDirectoryName(fileContentTablePath)); // Note that we are using a non-async file stream here. That's because we're doing lots of tiny writes for simplicity, // but tiny writes on an async stream end up blocking anyway while adding silly overhead. using (FileStream stream = FileUtilities.CreateFileStream( fileContentTablePath, FileMode.Create, FileAccess.Write, FileShare.Delete, // Do not write the file with SequentialScan since it will be reread in the subsequent build FileOptions.None)) { // We don't have anything in particular to correlate this file to, // so we are simply creating a unique correlation id that is used as part // of the header consistency check. FileEnvelopeId correlationId = FileEnvelopeId.Create(); s_fileEnvelope.WriteHeader(stream, correlationId); using (var writer = new BuildXLWriter(debug: false, stream: stream, leaveOpen: true, logStats: false)) { long numberOfEntriesPosition = writer.BaseStream.Position; writer.Write(0U); uint entriesWritten = 0; var hashBuffer = new byte[ContentHashingUtilities.HashInfo.ByteLength]; foreach (var fileAndEntryPair in m_entries) { // Skip saving anything with a TTL of zero. These entries were loaded // with a TTL of one (immediately decremented) and were not used since load. // See class remarks. if (fileAndEntryPair.Value.TimeToLive == 0) { numEvicted++; continue; } // Key: Volume and File ID fileAndEntryPair.Key.Serialize(writer); // Entry: USN, hash, time to live. writer.Write(fileAndEntryPair.Value.Usn.Value); fileAndEntryPair.Value.Hash.SerializeHashBytes(hashBuffer, 0); writer.Write(hashBuffer); writer.Write(fileAndEntryPair.Value.Length); writer.Write(fileAndEntryPair.Value.TimeToLive); entriesWritten++; } var endPosition = writer.BaseStream.Position; writer.BaseStream.Position = numberOfEntriesPosition; writer.Write(entriesWritten); writer.BaseStream.Position = endPosition; } s_fileEnvelope.FixUpHeader(stream, correlationId); } Counters.AddToCounter(FileContentTableCounters.NumEvicted, numEvicted); return(Unit.Void); }, ex => { throw new BuildXLException("Failure writing file content table", ex); }); }
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)); } }