private FakeFileStream CreateStream([NotNull] AbsolutePath path, FileAccess access, bool isReaderOnly, bool notifyTracker) { lock (readerWriterLock) { if (activeWriter != null) { throw ErrorFactory.System.FileIsInUse(path.GetText()); } if (!isReaderOnly && activeReaders.Any()) { throw ErrorFactory.System.FileIsInUse(path.GetText()); } var stream = new FakeFileStream(this, access, notifyTracker); if (isReaderOnly) { activeReaders.Add(stream); } else { activeWriter = stream; } return(stream); } }
public IFileStream Open(FileMode mode, FileAccess access, [NotNull] AbsolutePath path, bool isNewlyCreated, bool isAsync, bool notifyTracker) { Guard.NotNull(path, nameof(path)); bool isReaderOnly = access == FileAccess.Read; bool truncate = false; bool seekToEnd = false; switch (mode) { case FileMode.CreateNew: case FileMode.Create: case FileMode.Truncate: { truncate = true; isReaderOnly = false; break; } case FileMode.Append: { seekToEnd = true; isReaderOnly = false; break; } } FakeFileStream stream = CreateStream(path, access, isReaderOnly, notifyTracker); InitializeStream(stream, seekToEnd, truncate, isNewlyCreated); return(new FileStreamWrapper(stream, path.GetText, () => isAsync, stream.GetSafeFileHandle, _ => stream.Flush(), stream.Lock, stream.Unlock)); }
public void Add(long position, long length, [NotNull] FakeFileStream stream) { Guard.NotNull(owner, nameof(owner)); lock (owner.readerWriterLock) { if (rangesLocked.Any(range => range.IntersectsWith(position, length))) { throw ErrorFactory.System.CannotAccessFileProcessHasLocked(); } rangesLocked.Add(new LockRange(position, length, stream)); } }
public void Release([NotNull] FakeFileStream stream) { Guard.NotNull(stream, nameof(stream)); lock (owner.readerWriterLock) { for (int index = rangesLocked.Count - 1; index >= 0; index--) { if (rangesLocked[index].Owner == stream) { rangesLocked.RemoveAt(index); } } } }
private void CloseStream([NotNull] FakeFileStream stream) { lock (readerWriterLock) { if (activeWriter == stream) { activeWriter = null; } activeReaders.Remove(stream); if (deleteOnClose && !IsOpen()) { Parent.DeleteFile(Name, true); } } }
private static void InitializeStream([NotNull] FakeFileStream stream, bool seekToEnd, bool truncate, bool isNewlyCreated) { if (seekToEnd) { stream.Seek(0, SeekOrigin.End); stream.SetAppendOffsetToCurrentPosition(); } if (truncate) { stream.SetLength(0); if (!isNewlyCreated) { stream.EnableAccessKinds(FileAccessKinds.WriteRead); } } }
public void Remove(long position, long length, [NotNull] FakeFileStream stream) { Guard.NotNull(stream, nameof(stream)); lock (owner.readerWriterLock) { for (int index = rangesLocked.Count - 1; index >= 0; index--) { LockRange range = rangesLocked[index]; if (range.Position == position && range.Length == length && range.Owner == stream) { rangesLocked.RemoveAt(index); return; } } } throw ErrorFactory.System.SegmentIsAlreadyUnlocked(); }
public LockRange(long position, long length, [NotNull] FakeFileStream owner) { Position = position; Length = length; Owner = owner; }
public bool UnsafeIsLocked(long position, long length, [NotNull] FakeFileStream stream) { Guard.NotNull(stream, nameof(stream)); return(rangesLocked.Where(x => x.Owner != stream).Any(range => range.IntersectsWith(position, length))); }
public Stream GetStream(FileMode fileMode, FileAccess fileAccess, FileShare fileShare) { ValidateAccess(fileShare); switch (fileShare) { case FileShare.None: if (_openStreams.Any()) { throw new AccessViolationException(); } break; case FileShare.Read: if (_openStreams.Any(x => (x.FileAccess != FileAccess.Read) || (x.FileShare == FileShare.None))) { throw new AccessViolationException(); } break; case FileShare.Write: if (_openStreams.Any(x => (x.FileAccess != FileAccess.Write) || (x.FileShare == FileShare.None))) { throw new AccessViolationException(); } break; case FileShare.ReadWrite: if (_openStreams.Any(x => x.FileShare == FileShare.None)) { throw new AccessViolationException(); } break; case FileShare.Delete: throw new NotSupportedException(); case FileShare.Inheritable: throw new NotSupportedException(); default: throw new ArgumentOutOfRangeException(nameof(fileShare), fileShare, null); } var stream = new FakeFileStream( ContentAsBytes, fileMode, fileAccess, fileShare, () => LastWriteTimeUtc = _dateTimeProvider.Time(), flushedContent => { switch (fileAccess) { case FileAccess.Write: case FileAccess.ReadWrite: ContentAsBytes = flushedContent; break; } }, s => _openStreams.Remove(s)); _openStreams.Add(stream); return(stream); }