FileSystem.Unix.File.Move uses "rename" in more cases#40611
FileSystem.Unix.File.Move uses "rename" in more cases#40611carlossanlop merged 2 commits intodotnet:masterfrom
Conversation
bd7b3a0 to
5fa5b7a
Compare
e44a9a6 to
0f9ef8c
Compare
|
Sorry, this doesn't work as expected |
…hen possible, improve performance on file systems that do not support hard links, such as FAT
|
This version (bb59ae4) has been tested and works as expected |
0f9ef8c to
bb59ae4
Compare
|
@mandawah could you please look at the test failures? Various Move tests failed. You can see by clicking on Details above next to one of the legs, then the "view more details on Azure Pipelines" then the tests tab: |
|
Hello @danmosemsft, For instance: one test expects a "file deleted event" when a file is moved within the same directory. With current master implementation this is indeed the case, since "link then delete" is used. With my PR implementation, we use rename, so of course no file is deleted. I have to admit that I don't known how to handle this exactly, I am not familiar with corefx "philosophy" regarding test coverage. I feel that the test I took as an example above is written to validate that a given implementation doesn't change, i.e. "File.Move within same directory shall fire deleted event", rather than testing that the file was actually moved. I am ok with this, but this means that this test defines the behavior ("contract") of File.Move, and not only test the functionality. What I mean is that: if this test is defining the correct expected behavior, i.e. if the test is the specification of File.Move, then I will have to basically add some code to fire deleted event after rename. If not, then I can change the test (in this case basically I should probably delete it) because it may not make sens to ask for a delete event when the file is simply renamed/moved in general (regardless of however File.Move is actually implemented). So, my question is: where can I find the specification (or contracts) of File.Move regarding expected FileSystemWatcher events, etc.? Is the specification implicitly defined by those unit tests? Is it safe (I bet not) to change which events are fired? But then, last question: even in the current implementation, when some conditions are met, we use rename instead of link/delete. In this case we have a move (rename) without deleted event being fired... Is this really well defined and wanted? Unit Tests seem to be really tailored to this particular current implementation. Shall I change my code to mimic the current implementation regarding which events are fired? Or adapt the test for my implementation, with the risk of breaking contracts? Sorry for this long post, but I am new here and I need some guidance . Thank you in advance for you reply. |
|
I'm not sure either. I think the FSW tests have little to do with the implementation of our Move API and instead are designed to validate behavior in the face of the range of possible file system activity caused by any app by whatever means. They should continue to do that. |
|
Thanks for your reply. I understand that your opinion is that I shall add some code to "fake" a delete even though rename does not actually delete a file. Since rename will still also be used for "moving" a file from a name to another name with a different casing, we'll end-up with: File.Move("aa.txt", "bb.txt") firing deleted events I am not very confortable with this. I have the feeling that File.Move triggering deleted file events is strange in the first place, especially when really moving a file on the same device: we tell the watcher that there is a deleted file, but not that there is a created file, such that it could conclude that there is one less file than before, which would be wrong. I don't know... I need to think about the best way to resolve this, thanks. Any by the way I don't know yet how to produce a deleted event out of nothing, I need to look at it. |
|
@carlossanlop @JeremyKuhne own this area and can give guidance. |
|
I don't think we should be updating the watcher to fabricate delete events (any more than we already do with renames). I also don't think that we should attempt to make We'd be going down a slippery slope trying anything else. We don't control the file system, we should just tell it like it is. @carlossanlop, do you agree and/or have any other thoughts? |
carlossanlop
left a comment
There was a problem hiding this comment.
I agree with @JeremyKuhne. We talked about this PR later today, and it doesn't make sense to have a test that expects an OS event to be fired. @mandawah please update the unit test to not expect a delete event anymore.
|
OK thanks @JeremyKuhne @carlossanlop , I'll do what you said. Please be aware that this may involve simply removing some tests since only one single functionality is tested per test (which is good). |
fbdd9b8 to
05f8418
Compare
…eSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible
05f8418 to
95d205c
Compare
|
@carlossanlop @JeremyKuhne is this PR good for merge? It also has the approval. |
* FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible
| Interop.Sys.FileStatus sourceStat, destStat; | ||
| if (Interop.Sys.LStat(sourceFullPath, out sourceStat) == 0 && // source file exists | ||
| Interop.Sys.LStat(destFullPath, out destStat) == 0 && // dest file exists | ||
| sourceStat.Dev == destStat.Dev && // source and dest are on the same device |
…395) * FileSystem.Unix.File.Move uses "rename" in more cases (dotnet#40611) * FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible * [FileSystem] ReAdd check for same device Co-authored-by: Sylvain <sf@ellisys.com> Co-authored-by: Mitchell Hwang <mihw@microsoft.com>
* FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible
…otnet#40611) (#396) * FileSystem.Unix.File.Move uses "rename" in more cases (dotnet#40611) * FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible * [FileSystem] ReAdd check for same device Co-authored-by: Sylvain <sf@ellisys.com> Co-authored-by: Mitchell Hwang <mihw@microsoft.com>
…40611) * FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible Commit migrated from dotnet/corefx@89b087b
with the goal of avoiding link/copy when possible, since not reverting to LinkOrCopy when not necessary improves performance on file systems that do not support hard links, such as FAT.
Before this PR "rename" is used only when source and dest file exist and are on the same device and are the same file on that device.
With this PR "rename" is used when source file exist and source and dest are on the same device and either source and dest are the same file on that device (as before) or dest file does not exist (new).
This latter case permits to use "rename" for simply moving a file to an non existing new name on the same device, instead of "LinkOrCopyFile". Consequently, calling File.Move for such cases on file systems that do not support link (e.g. FAT) will result in much faster operations, because copy won't be used.
See mono/mono#16435