Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Fast file enumeration for Windows #25426

Merged
merged 20 commits into from
Nov 30, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0fc66cd
Fast file enumeration for Windows
JeremyKuhne Nov 22, 2017
c4f14fa
Fix comment and method name for Unix
JeremyKuhne Nov 22, 2017
c0622df
Change BOOLEAN accessibility to internal and add missing unix PathInt…
JeremyKuhne Nov 22, 2017
9b8c50e
Add issue for IsolatedStorage test on Unix
JeremyKuhne Nov 22, 2017
c8c411e
Change FindEnumerable to be IEnumerator directly.
JeremyKuhne Nov 22, 2017
d711235
Fix closure allocations and address other feedback.
JeremyKuhne Nov 22, 2017
39ec45d
Use string.Create(), tweak enumerable disposal
JeremyKuhne Nov 23, 2017
a4a78d2
Add extended prefix for UAP to fix test failure.
JeremyKuhne Nov 24, 2017
20f882f
Push initial handle creation up front and ensure handle closure for e…
JeremyKuhne Nov 24, 2017
8099aad
Add missing CloseHandle file to Watcher and Ports projects.
JeremyKuhne Nov 27, 2017
f0d6ec1
Fix disposal gate
JeremyKuhne Nov 27, 2017
7030750
Change to use RtlNtStatusToDosError (which underlies Lsa method we we…
JeremyKuhne Nov 28, 2017
a61ca3e
Fix outerloop test.
JeremyKuhne Nov 28, 2017
b7783fb
Tweak the comment and remove the ConditionalTheory as it isn't needed.
JeremyKuhne Nov 28, 2017
2b5c49e
Align BOOLEAN with BOOL. Clean DosMatcher signature.
JeremyKuhne Nov 30, 2017
9cbe9c4
Address feedback to make the enumerator threadsafe.
JeremyKuhne Nov 30, 2017
6da9522
Add JKotas regression test and lock dispose
JeremyKuhne Nov 30, 2017
1829bfb
Address various feedback.
JeremyKuhne Nov 30, 2017
017394e
Tweak tests
JeremyKuhne Nov 30, 2017
77eeccf
Expand length for ValueStringBuilder with nulls like StringBuilder do…
JeremyKuhne Nov 30, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions src/System.IO.FileSystem/tests/Directory/EnumerableTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,21 @@ public void FileEnumeratorIsThreadSafe()
for (int i = 0; i < 100; i++)
File.Create(Path.Combine(directory, GetTestFileName())).Dispose();

new ThreadSafeRepro().Execute(directory);
// We are really only trying to make sure we don't terminate the process.
// Throwing IOException at this point to try and flush out other problems
// like bad handles. Can narrow the throw if this isn't reliable.

try
{
new ThreadSafeRepro().Execute(directory);
}
catch (IOException)
{
throw;
}
catch (Exception)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine. Another approach would be:

catch (Exception e) when (!(e is IOException)) { }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update it as I'm updating VSB.

{
}
}

class ThreadSafeRepro
Expand All @@ -46,17 +60,24 @@ void Work()
if (x != null)
Enumerate(x);
} while (!token.IsCancellationRequested);
token.ThrowIfCancellationRequested();
}

new Task(Work, token).Start();
new Task(Work, token).Start();
for (int i = 0; i < 1000; i++)
Task taskOne = Task.Run(action: Work);
Task taskTwo = Task.Run(action: Work);

try
{
for (int i = 0; i < 1000; i++)
{
_enumerator = Directory.EnumerateFiles(directory).GetEnumerator();
Enumerate(_enumerator);
}
}
finally
{
_enumerator = Directory.EnumerateFiles(directory).GetEnumerator();
Enumerate(_enumerator);
source.Cancel();
Task.WaitAll(taskOne, taskTwo);
}
source.Cancel();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to do:

Task t1 = Task.Run(Work);
Task t2 = Task.Run(Work);
...
source.Cancel();
Task.WaitAll(t1, t2);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized this as well. Thanks :)

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -793,15 +793,19 @@ public void WindowsSearchPatternWithDoubleDots_Desktop()
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)]
public void WindowsSearchPatternWithDoubleDots_Core()
public void SearchPatternWithDoubleDots_Core()
{
// Search pattern with double dots no longer throws ArgumentException
string directory = Directory.CreateDirectory(GetTestFilePath()).FullName;
Assert.Throws<DirectoryNotFoundException>(() => GetEntries(directory, Path.Combine("..ab ab.. .. abc..d", "abc..")));
GetEntries(directory, "..");
GetEntries(directory, @".." + Path.DirectorySeparatorChar);

Assert.Throws<DirectoryNotFoundException>(() => GetEntries(directory, Path.Combine("..ab ab.. .. abc..d", "abc", "..")));
GetEntries(directory, Path.Combine("..ab ab.. .. abc..d", "..", "abc"));
Assert.Throws<DirectoryNotFoundException>(() => GetEntries(directory, Path.Combine("..", "..ab ab.. .. abc..d", "abc")));
Assert.Throws<DirectoryNotFoundException>(() => GetEntries(directory, Path.Combine("..", "..ab ab.. .. abc..d", "abc") + Path.DirectorySeparatorChar));
}

private static char[] OldWildcards = new char[] { '*', '?' };
Expand Down Expand Up @@ -1009,22 +1013,6 @@ public void UnixSearchPatternDirectoryValidChar(string valid)
}
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Search pattern with DoubleDots on Unix
public void UnixSearchPatternWithDoubleDots()
{
// search pattern is valid but directory doesn't exist
Assert.Throws<DirectoryNotFoundException>(() => GetEntries(TestDirectory, Path.Combine("..ab ab.. .. abc..d", "abc..")));

string directory = Directory.CreateDirectory(GetTestFilePath()).FullName;
GetEntries(directory, "..");
GetEntries(directory, @".." + Path.DirectorySeparatorChar);
GetEntries(directory, Path.Combine("..ab ab.. .. abc..d", "abc", ".."));
GetEntries(directory, Path.Combine("..ab ab.. .. abc..d", "..", "abc"));
GetEntries(directory, Path.Combine("..", "..ab ab.. .. abc..d", "abc"));
GetEntries(directory, Path.Combine("..", "..ab ab.. .. abc..d", "abc") + Path.DirectorySeparatorChar);
}

#endregion
}
}