Path: blob/master/test/jdk/java/nio/file/WatchService/MayFlies.java
41153 views
/*1* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 7164570 719146725* @summary Test that CREATE and DELETE events are paired for very26* short lived files27* @library ..28* @run main MayFlies29* @key randomness30*/3132import java.nio.file.*;33import static java.nio.file.StandardWatchEventKinds.*;34import java.util.*;35import java.util.concurrent.*;3637public class MayFlies {3839static volatile boolean stopped;4041static volatile boolean failure;4243/**44* Continuously creates short-lived files in a directory until {@code45* stopped} is set to {@code true}.46*/47static class MayFlyHatcher implements Runnable {48static final Random rand = new Random();4950private final Path dir;51private final String prefix;5253private MayFlyHatcher(Path dir, String prefix) {54this.dir = dir;55this.prefix = prefix;56}5758static void start(Path dir, String prefix) {59MayFlyHatcher hatcher = new MayFlyHatcher(dir, prefix);60new Thread(hatcher).start();61}6263public void run() {64try {65int n = 0;66while (!stopped) {67Path name = dir.resolve(prefix + (++n));68Files.createFile(name);69if (rand.nextBoolean())70Thread.sleep(rand.nextInt(500));71Files.delete(name);72Thread.sleep(rand.nextInt(100));73}74System.out.format("%d %ss hatched%n", n, prefix);75} catch (Exception x) {76failure = true;77x.printStackTrace();78}79}80}8182/**83* Test phases.84*/85static enum Phase {86/**87* Short-lived files are being created88*/89RUNNING,90/**91* Draining the final events92*/93FINISHING,94/**95* No more events or overflow detected96*/97FINISHED98};99100101public static void main(String[] args) throws Exception {102103// schedules file creation to stop after 10 seconds104ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();105pool.schedule(106new Runnable() { public void run() { stopped = true; }},10710, TimeUnit.SECONDS);108109Path dir = TestUtil.createTemporaryDirectory();110111Set<Path> entries = new HashSet<>();112int nCreateEvents = 0;113boolean overflow = false;114115try (WatchService watcher = FileSystems.getDefault().newWatchService()) {116WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE);117118// start hatching Mayflies119MayFlyHatcher.start(dir, "clinger");120MayFlyHatcher.start(dir, "crawler");121MayFlyHatcher.start(dir, "burrower");122MayFlyHatcher.start(dir, "swimmer");123124Phase phase = Phase.RUNNING;125while (phase != Phase.FINISHED) {126// during the running phase then poll for 1 second.127// once the file creation has stopped then move to the finishing128// phase where we do a long poll to ensure that all events have129// been read.130int time = (phase == Phase.RUNNING) ? 1 : 15;131key = watcher.poll(time, TimeUnit.SECONDS);132if (key == null) {133if (phase == Phase.RUNNING && stopped)134phase = Phase.FINISHING;135else if (phase == Phase.FINISHING)136phase = Phase.FINISHED;137} else {138// process events139for (WatchEvent<?> event: key.pollEvents()) {140if (event.kind() == ENTRY_CREATE) {141Path name = (Path)event.context();142boolean added = entries.add(name);143if (!added)144throw new RuntimeException("Duplicate ENTRY_CREATE event");145nCreateEvents++;146} else if (event.kind() == ENTRY_DELETE) {147Path name = (Path)event.context();148boolean removed = entries.remove(name);149if (!removed)150throw new RuntimeException("ENTRY_DELETE event without ENTRY_CREATE event");151} else if (event.kind() == OVERFLOW) {152overflow = true;153phase = Phase.FINISHED;154} else {155throw new RuntimeException("Unexpected event: " + event.kind());156}157}158key.reset();159}160}161162System.out.format("%d ENTRY_CREATE events read%n", nCreateEvents);163164// there should be a DELETE event for each CREATE event and so the165// entries set should be empty.166if (!overflow && !entries.isEmpty())167throw new RuntimeException("Missed " + entries.size() + " DELETE event(s)");168169170} finally {171try {172TestUtil.removeAll(dir);173} finally {174pool.shutdown();175}176}177178if (failure)179throw new RuntimeException("Test failed - see log file for details");180}181}182183184