-
Notifications
You must be signed in to change notification settings - Fork 0
Improved overflow support: Recursive directory watches #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved overflow support: Recursive directory watches #27
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## improved-overflow-support-main #27 +/- ##
==================================================================
- Coverage 81.4% 81.2% -0.3%
- Complexity 121 129 +8
==================================================================
Files 16 16
Lines 549 532 -17
Branches 54 54
==================================================================
- Hits 447 432 -15
+ Misses 72 63 -9
- Partials 30 37 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
JDKFileTreeWatch)
DavyLandman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! A lot of remove code. I like the idea to make it an actual tree, that will also reduce the pressure on the map. Although it will now cause multiple lookups in smaller maps. Almost makes you consider some kind of sortedmap/trie structure to quickly jump to the right child entry.
Some larger concerns I have with the current proposed changes:
- It looks like the updating of the child directories (and especially missed nested child directories) depends on the overflow handling strategy. I do not think that is a wise dependency. Maybe we should add a test parameter to the torture test that cycles through all 3 enum values of the overflow handler
- When implementing the original code my concern was to avoid iterating the filesystem more than needed, in profiling I noticed that had quite a perf hit, especially in larger directory hierarchies.
- Similar point is with the scheduling of work on the Thread pool. My original approach has been to get the event that happened to the user as soon as we get them (as soon as we can), and do our internal bookkeeping in the background. For an IDE we don't want to have the event get in the back of the queue after our bookkeeping. I might be mistaken, but I have the feeling the current code is chaining a lot in
andThenclauses without pushing them onto separate workjobs. If the design is that the original event gets pushed to the consumer first, and only after that is done do we handle the book-keeping, its a bit better, I mean, we might leave some cpu-cores idling, but at least we don't delay events.
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java
Outdated
Show resolved
Hide resolved
sungshik
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Davy! I addressed (and tentatively closed) all comments except this one, which requires more thought...
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java
Outdated
Show resolved
Hide resolved
…erve the integrity of its internal child watchers
…t (after an overflow event)
src/test/java/engineering/swat/watch/impl/JDKFileTreeWatchTests.java
Outdated
Show resolved
Hide resolved
src/test/java/engineering/swat/watch/impl/JDKFileTreeWatchTests.java
Outdated
Show resolved
Hide resolved
…verridden in other subclasses)
… already-queued events after close)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today's series of commits fix the following issues:
- Primarily, it adds the filtering mechanism and revises the test (old one deleted, new one added)
- Also, it fixes the closing issue we encountered (unrelated to filtering)
- Also, it fixes a few small things related to relativization (also unrelated to filtering)
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKRecursiveDirectoryWatch.java
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/overflows/IndexingRescanner.java
Show resolved
Hide resolved
DavyLandman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small clarification questions.
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java
Outdated
Show resolved
Hide resolved
…for usage assumption)
…support/jdk-file-tree-watch
Note
To avoid diff noise, enable "Hide whitespace" when reviewing the code. (I pulled a few methods from an inner class to its outer class, so indentation changed.)
Overview
This PR:
JDKRecursiveDirectoryWatchto rely on the new mechanism to auto-handle overflows. These are the minimal changes required to make it work.JDKFileTreeWatchas an alternative recursive directory watch. I originally wrote this alternative as a proof-of-concept to better understand/design how auto-handling of overflows could be a standalone thing (i.e., also use it with file/non-recursive directory watches), and how the interaction with recursive directory watches would play out.Task list
If we chooseJDKRecursiveDirectoryWatch, then it needs to be tidied up a bit (update comments etc.)Similarities between the types of watches
Both types of recursive directory watches are containers for a collection of internal
JDKDirectoryWatchobjects (one for each subdirectory in scope), subject to the following principles:JDKDirectoryWatchfor each subdirectory.CREATEDevents for new subdirectories may have been missed. So, after starting the internal watches, send anOVERFLOWevent to the internal watch of the top-level directory. (It is forwarded to the other internal watches, as described below.) Update: This isn't needed forJDKFileTreeWatch(see the relevant comment in the code).x, in addition to calling the event-handler:OVERFLOW: Forward the event to the internal watches for subdirectoriesy1,y2, ..., ofx.CREATED, new subdirectoryy: (1) Start an internal watch fory. (2) Between the creation ofyand the start of the internal watch, events may have been missed. So, after starting the internal watch, send anOVERFLOWevent to it.DELETED, old subdirectoryy: Stop the internal watch fory.MODIFIED: -Differences
Using
JDKRecursiveDirectoryWatch, the internal watches are stored "flat" inside a singleJDKRecursiveDirectoryWatchobject. UsingJDKFileTreeWatch, the internal watches are stored "hierarchical" inside a tree ofJDKFileTreeWatchobjects (one internal watch perJDKFileTreeWatch).For instance, suppose we have the following (sub)directories:
foofoo/bar1foo/bar2foo/bar3foo/bar3/baz1foo/bar3/baz2The structure of
JDKRecursiveDirectoryWatchlooks as follows:graph TB subgraph Foo[JDKRecursiveDirectoryWatch] direction LR FooInner["JDKDirectoryWatch /foo"] ~~~ Bar1Inner["JDKDirectoryWatch /foo/bar1"] ~~~ Bar2Inner["JDKDirectoryWatch /foo/bar2"] Bar3Inner["JDKDirectoryWatch /foo/bar3"] ~~~ Baz1Inner["JDKDirectoryWatch /foo/bar3/baz1"] ~~~ Baz2Inner["JDKDirectoryWatch /foo/bar3/baz2"] endThe structure of
JDKFileTreeWatchlooks as follows:graph TB subgraph Foo[JDKFileTreeWatch] FooInner["JDKDirectoryWatch /foo"] end subgraph Bar1[JDKFileTreeWatch] Bar1Inner["JDKDirectoryWatch /foo/bar1"] end subgraph Bar2[JDKFileTreeWatch] Bar2Inner["JDKDirectoryWatch /foo/bar2"] end subgraph Bar3[JDKFileTreeWatch] Bar3Inner["JDKDirectoryWatch /foo/bar3"] end subgraph Baz1[JDKFileTreeWatch] Baz1Inner["JDKDirectoryWatch /foo/bar3/baz1"] end subgraph Baz2[JDKFileTreeWatch] Baz2Inner["JDKDirectoryWatch /foo/bar3/baz2"] end Foo --> Bar1 Foo --> Bar2 Foo --> Bar3 Bar3 --> Baz1 Bar3 --> Baz2