53 * Tests that OVERFLOW events are not retreived with other events. |
53 * Tests that OVERFLOW events are not retreived with other events. |
54 */ |
54 */ |
55 static void testOverflowEvent(Path dir) |
55 static void testOverflowEvent(Path dir) |
56 throws IOException, InterruptedException |
56 throws IOException, InterruptedException |
57 { |
57 { |
58 WatchService watcher = dir.getFileSystem().newWatchService(); |
58 try (WatchService watcher = dir.getFileSystem().newWatchService()) { |
59 try { |
|
60 dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); |
59 dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE); |
61 |
60 |
62 // create a lot of files |
61 // create a lot of files |
63 int n = 1024; |
62 int n = 1024; |
64 Path[] files = new Path[n]; |
63 Path[] files = new Path[n]; |
65 for (int i=0; i<n; i++) { |
64 for (int i=0; i<n; i++) { |
66 files[i] = dir.resolve("foo" + i).createFile(); |
65 files[i] = Files.createFile(dir.resolve("foo" + i)); |
67 } |
66 } |
68 |
67 |
69 // give time for events to accumulate (improve chance of overflow) |
68 // give time for events to accumulate (improve chance of overflow) |
70 Thread.sleep(1000); |
69 Thread.sleep(1000); |
71 |
70 |
72 // check that we see the create events (or overflow) |
71 // check that we see the create events (or overflow) |
73 drainAndCheckOverflowEvents(watcher, ENTRY_CREATE, n); |
72 drainAndCheckOverflowEvents(watcher, ENTRY_CREATE, n); |
74 |
73 |
75 // delete the files |
74 // delete the files |
76 for (int i=0; i<n; i++) { |
75 for (int i=0; i<n; i++) { |
77 files[i].delete(); |
76 Files.delete(files[i]); |
78 } |
77 } |
79 |
78 |
80 // give time for events to accumulate (improve chance of overflow) |
79 // give time for events to accumulate (improve chance of overflow) |
81 Thread.sleep(1000); |
80 Thread.sleep(1000); |
82 |
81 |
83 // check that we see the delete events (or overflow) |
82 // check that we see the delete events (or overflow) |
84 drainAndCheckOverflowEvents(watcher, ENTRY_DELETE, n); |
83 drainAndCheckOverflowEvents(watcher, ENTRY_DELETE, n); |
85 } finally { |
|
86 watcher.close(); |
|
87 } |
84 } |
88 } |
85 } |
89 |
86 |
90 static void drainAndCheckOverflowEvents(WatchService watcher, |
87 static void drainAndCheckOverflowEvents(WatchService watcher, |
91 WatchEvent.Kind<?> expectedKind, |
88 WatchEvent.Kind<?> expectedKind, |
145 entries[i].deleteIfExists(); |
142 entries[i].deleteIfExists(); |
146 if (rand.nextBoolean()) |
143 if (rand.nextBoolean()) |
147 entries[i].create(); |
144 entries[i].create(); |
148 } |
145 } |
149 |
146 |
150 WatchService watcher = dir.getFileSystem().newWatchService(); |
147 try (WatchService watcher = dir.getFileSystem().newWatchService()) { |
151 try { |
|
152 dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); |
148 dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); |
153 |
149 |
154 // do several rounds of noise and test |
150 // do several rounds of noise and test |
155 for (int round=0; round<10; round++) { |
151 for (int round=0; round<10; round++) { |
156 |
152 |
167 |
163 |
168 // process events and ensure that we don't get repeated modify |
164 // process events and ensure that we don't get repeated modify |
169 // events for the same file. |
165 // events for the same file. |
170 WatchKey key = watcher.poll(15, TimeUnit.SECONDS); |
166 WatchKey key = watcher.poll(15, TimeUnit.SECONDS); |
171 while (key != null) { |
167 while (key != null) { |
172 Set<Path> modified = new HashSet<Path>(); |
168 Set<Path> modified = new HashSet<>(); |
173 for (WatchEvent<?> event: key.pollEvents()) { |
169 for (WatchEvent<?> event: key.pollEvents()) { |
174 WatchEvent.Kind<?> kind = event.kind(); |
170 WatchEvent.Kind<?> kind = event.kind(); |
175 Path file = (kind == OVERFLOW) ? null : (Path)event.context(); |
171 Path file = (kind == OVERFLOW) ? null : (Path)event.context(); |
176 if (kind == ENTRY_MODIFY) { |
172 if (kind == ENTRY_MODIFY) { |
177 boolean added = modified.add(file); |
173 boolean added = modified.add(file); |
186 if (!key.reset()) |
182 if (!key.reset()) |
187 throw new RuntimeException("Key is no longer valid"); |
183 throw new RuntimeException("Key is no longer valid"); |
188 key = watcher.poll(2, TimeUnit.SECONDS); |
184 key = watcher.poll(2, TimeUnit.SECONDS); |
189 } |
185 } |
190 } |
186 } |
191 |
|
192 } finally { |
|
193 watcher.close(); |
|
194 } |
187 } |
195 } |
188 } |
196 |
189 |
197 static class DirectoryEntry { |
190 static class DirectoryEntry { |
198 private final Path file; |
191 private final Path file; |
199 DirectoryEntry(Path file) { |
192 DirectoryEntry(Path file) { |
200 this.file = file; |
193 this.file = file; |
201 } |
194 } |
202 void create() throws IOException { |
195 void create() throws IOException { |
203 if (file.notExists()) |
196 if (Files.notExists(file)) |
204 file.createFile(); |
197 Files.createFile(file); |
205 |
198 |
206 } |
199 } |
207 void deleteIfExists() throws IOException { |
200 void deleteIfExists() throws IOException { |
208 file.deleteIfExists(); |
201 Files.deleteIfExists(file); |
209 } |
202 } |
210 void modifyIfExists() throws IOException { |
203 void modifyIfExists() throws IOException { |
211 if (file.exists()) { |
204 if (Files.exists(file)) { |
212 OutputStream out = file.newOutputStream(StandardOpenOption.APPEND); |
205 try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) { |
213 try { |
|
214 out.write("message".getBytes()); |
206 out.write("message".getBytes()); |
215 } finally { |
|
216 out.close(); |
|
217 } |
207 } |
218 } |
208 } |
219 } |
209 } |
220 } |
210 } |
221 |
211 |