Skip to content

Commit 6a7df86

Browse files
committed
Use file names to store child watches (instead of full paths)
1 parent 4582d23 commit 6a7df86

File tree

2 files changed

+39
-13
lines changed

2 files changed

+39
-13
lines changed

src/main/java/engineering/swat/watch/WatchEvent.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,16 @@ public enum Kind {
6868
private final Path rootPath;
6969
private final Path relativePath;
7070

71+
private static final Path EMPTY_PATH = Path.of("");
72+
7173
public WatchEvent(Kind kind, Path rootPath) {
7274
this(kind, rootPath, null);
7375
}
7476

7577
public WatchEvent(Kind kind, Path rootPath, @Nullable Path relativePath) {
7678
this.kind = kind;
7779
this.rootPath = rootPath;
78-
this.relativePath = relativePath == null ? Path.of("") : relativePath;
80+
this.relativePath = relativePath == null ? EMPTY_PATH : relativePath;
7981
}
8082

8183
public Kind getKind() {
@@ -112,7 +114,11 @@ public Path calculateFullPath() {
112114
* efficient than, {@code calculateFullPath().getFileName()}.
113115
*/
114116
public @Nullable Path getFileName() {
115-
return relativePath.getParent() == null ? rootPath.getFileName() : relativePath.getFileName();
117+
var fileName = relativePath.getFileName();
118+
if (fileName == null || fileName.equals(EMPTY_PATH)) {
119+
fileName = rootPath.getFileName();
120+
}
121+
return fileName;
116122
}
117123

118124
@Override

src/main/java/engineering/swat/watch/impl/jdk/JDKFileTreeWatch.java

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.concurrent.ConcurrentHashMap;
3434
import java.util.concurrent.Executor;
3535
import java.util.function.BiConsumer;
36+
import java.util.function.Consumer;
3637
import java.util.function.Function;
3738

3839
import org.apache.logging.log4j.LogManager;
@@ -107,33 +108,42 @@ private class ChildWatchesUpdater implements BiConsumer<EventHandlingWatch, Watc
107108
public void accept(EventHandlingWatch watch, WatchEvent event) {
108109
switch (event.getKind()) {
109110
case OVERFLOW: acceptOverflow(); break;
110-
case CREATED: acceptCreated(event.calculateFullPath()); break;
111-
case DELETED: acceptDeleted(event.calculateFullPath()); break;
111+
case CREATED: getFileNameAndThen(event, this::acceptCreated); break;
112+
case DELETED: getFileNameAndThen(event, this::acceptDeleted); break;
112113
case MODIFIED: break;
113114
}
114115
}
115116

117+
private void getFileNameAndThen(WatchEvent event, Consumer<Path> consumer) {
118+
var child = event.getFileName();
119+
if (child != null) {
120+
consumer.accept(child);
121+
} else {
122+
logger.error("Could not get file name of event: {}", event);
123+
}
124+
}
125+
116126
private void acceptOverflow() {
117127
for (var childWatch : childWatches.values()) {
118128
reportOverflowTo(childWatch);
119129
}
120130
}
121131

122-
private void acceptCreated(Path fullPath) {
123-
if (Files.isDirectory(fullPath)) {
124-
var childWatch = openChildWatch(fullPath);
132+
private void acceptCreated(Path child) {
133+
if (Files.isDirectory(path.resolve(child))) {
134+
var childWatch = openChildWatch(child);
125135
// Events in the newly created directory might have been missed
126136
// between its creation and setting up its watch. So, generate
127137
// an `OVERFLOW` event for the watch.
128138
reportOverflowTo(childWatch);
129139
}
130140
}
131141

132-
private void acceptDeleted(Path fullPath) {
142+
private void acceptDeleted(Path child) {
133143
try {
134-
closeChildWatch(fullPath);
144+
closeChildWatch(child);
135145
} catch (IOException e) {
136-
logger.error("Could not close (nested) file tree watch for: {} ({})", fullPath, e);
146+
logger.error("Could not close (nested) file tree watch for: {} ({})", path.resolve(child), e);
137147
}
138148
}
139149

@@ -145,9 +155,10 @@ private void reportOverflowTo(JDKFileTreeWatch childWatch) {
145155
}
146156

147157
private JDKFileTreeWatch openChildWatch(Path child) {
148-
Function<Path, JDKFileTreeWatch> newChildWatch = p -> new JDKFileTreeWatch(
149-
rootPath, rootPath.relativize(child), exec, eventHandler);
158+
assert !child.isAbsolute();
150159

160+
Function<Path, JDKFileTreeWatch> newChildWatch = p -> new JDKFileTreeWatch(
161+
rootPath, relativePathParent.resolve(child), exec, eventHandler);
151162
var childWatch = childWatches.computeIfAbsent(child, newChildWatch);
152163
try {
153164
childWatch.startIfFirstTime();
@@ -158,6 +169,8 @@ private JDKFileTreeWatch openChildWatch(Path child) {
158169
}
159170

160171
private void closeChildWatch(Path child) throws IOException {
172+
assert !child.isAbsolute();
173+
161174
var childWatch = childWatches.remove(child);
162175
if (childWatch != null) {
163176
childWatch.close();
@@ -212,7 +225,14 @@ public synchronized void close() throws IOException {
212225
protected synchronized void start() throws IOException {
213226
internal.open();
214227
try (var children = Files.find(path, 1, (p, attrs) -> p != path && attrs.isDirectory())) {
215-
children.forEach(this::openChildWatch);
228+
children.forEach(p -> {
229+
var child = p.getFileName();
230+
if (child != null) {
231+
openChildWatch(child);
232+
} else {
233+
logger.error("File tree watch (for: {}) could not open a child watch for: {}", path, p);
234+
}
235+
});
216236
} catch (IOException e) {
217237
logger.error("File tree watch (for: {}) could not iterate over its children ({})", path, e);
218238
}

0 commit comments

Comments
 (0)