/* * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
staticenum TestCase {
WRITABLE, // just verifies that we can create a file in our 'writable-lockfile-dir'
CLOSE, // checks that closing a FileHandler removes its lock file
CREATE_FIRST, // verifies that 'writable-lockfile-dir' contains no lock, then creates a first FileHandler.
CREATE_NEXT, // verifies that 'writable-lockfile-dir' contains a single lock, then creates the next FileHandler
REUSE, // verifies that zombie lock files can be reused
CLEANUP // removes "writable-lockfile-dir"
};
publicstaticvoid main(String... args) throws IOException { // we'll base all file creation attempts on the system temp directory, // %t
File writableDir = setup();
System.out.println("Writable dir is: " + writableDir.getAbsolutePath()); // we now have one writable directory to work with: // writableDir if (args == null || args.length == 0) {
args = new String[] { "WRITABLE", "CLOSE", "CLEANUP" };
} try {
runTests(writableDir, args);
} catch (RuntimeException | IOException | Error x) { // some error occured: cleanup delete(writableDir); throw x;
}
}
/** * @param writableDir in which log and lock file are created * @throws SecurityException * @throws RuntimeException * @throws IOException
*/ privatestaticvoid runTests(File writableDir, String... args) throws SecurityException,
RuntimeException, IOException { for (String arg : args) { switch(TestCase.valueOf(arg)) { // Test 1: makes sure we can create FileHandler in writable directory case WRITABLE: checkWritable(writableDir); break; // Test 2: verifies that FileHandler.close() cleans up its lock file case CLOSE: testFileHandlerClose(writableDir); break; // Test 3: creates the first file handler case CREATE_FIRST: testFileHandlerCreate(writableDir, true); break; // Test 4, 5, ... creates the next file handler case CREATE_NEXT: testFileHandlerCreate(writableDir, false); break; // Checks that zombie lock files are reused appropriatly case REUSE: testFileHandlerReuse(writableDir); break; // Removes the writableDir case CLEANUP: delete(writableDir); break; default: thrownew RuntimeException("No such test case: " + arg);
}
}
}
/** * @param writableDir in which log and lock file are created * @throws SecurityException * @throws RuntimeException * @throws IOException
*/ privatestaticvoid checkWritable(File writableDir) throws SecurityException,
RuntimeException, IOException { // Test 1: make sure we can create/delete files in the writable dir. final File file = new File(writableDir, "test.txt"); if (!createFile(file, false)) { thrownew IOException("Can't create " + file + "\n\tUnable to run test");
} else { delete(file);
}
}
privatestatic FileHandler createFileHandler(File writableDir) throws SecurityException,
RuntimeException, IOException { // Test 1: make sure we can create FileHandler in writable directory try {
FileHandler handler = new FileHandler("%t/" + WRITABLE_DIR + "/log.log");
handler.publish(new LogRecord(Level.INFO, handler.toString()));
handler.flush(); return handler;
} catch (IOException ex) { thrownew RuntimeException("Test failed: should have been able"
+ " to create FileHandler for " + "%t/" + WRITABLE_DIR
+ "/log.log in writable directory.", ex);
}
}
privatestatic List<File> listLocks(File writableDir, boolean print) throws IOException {
List<File> locks = new ArrayList<>(); for (File f : writableDir.listFiles()) { if (print) {
System.out.println("Found file: " + f.getName());
} if (f.getName().endsWith(".lck")) {
locks.add(f);
}
} return locks;
}
FileHandler handler1 = createFileHandler(writableDir);
System.out.println("handler created: " + handler1);
List<File> after = listLocks(writableDir, true);
System.out.println("after creating handler: " + after.size() + " locks found"); if (after.size() != 1) { thrownew RuntimeException("Unexpected number of lock files found for "
+ handler1 + ": " + after);
} final File lock = after.get(0);
after.clear();
handler1.close();
after = listLocks(writableDir, true);
System.out.println("after closing handler: " + after.size() + " locks found"); if (!after.isEmpty()) { thrownew RuntimeException("Unexpected number of lock files found for "
+ handler1 + ": " + after);
} if (!createFile(lock, false)) { thrownew IOException("Can't create fake lock file: " + lock);
} try {
before = listLocks(writableDir, true);
System.out.println("before: " + before.size() + " locks found"); if (before.size() != 1) { thrownew RuntimeException("Unexpected number of lock files found: "
+ before + " expected [" + lock + "].");
}
FileHandler handler2 = createFileHandler(writableDir);
System.out.println("handler created: " + handler2);
after = listLocks(writableDir, true);
System.out.println("after creating handler: " + after.size() + " locks found");
after.removeAll(before); if (!after.isEmpty()) { thrownew RuntimeException("Unexpected lock file found: " + after
+ "\n\t" + lock + " should have been reused");
}
handler2.close();
System.out.println("handler closed: " + handler2);
List<File> afterClose = listLocks(writableDir, true);
System.out.println("after closing handler: " + afterClose.size() + " locks found"); if (!afterClose.isEmpty()) { thrownew RuntimeException("Zombie lock file detected: " + afterClose);
}
if (supportsLocking) {
handler2 = null; try (FileChannel fc = FileChannel.open(lock.toPath(), CREATE_NEW, APPEND, WRITE)) {
if (fc.tryLock() != null) {
System.out.println("locked: " + lock);
handler2 = createFileHandler(writableDir);
System.out.println("handler created: " + handler2);
after = listLocks(writableDir, true);
System.out.println("after creating handler: " + after.size()
+ " locks found");
after.removeAll(before); if (after.size() != 1) { thrownew RuntimeException("Unexpected lock files found: " + after
+ "\n\t" + lock + " should not have been reused");
}
} else { thrownew RuntimeException("Failed to lock: " + lock);
}
} finally { if (handler2 != null) handler2.close(); delete(lock);
}
}
} finally {
List<File> finalLocks = listLocks(writableDir, false);
System.out.println("end: " + finalLocks.size() + " locks found"); delete(writableDir);
}
}
privatestaticvoid testFileHandlerCreate(File writableDir, boolean first) throws IOException {
List<File> before = listLocks(writableDir, true);
System.out.println("before: " + before.size() + " locks found"); try { if (first && !before.isEmpty()) { thrownew RuntimeException("Expected no lock file! Found: " + before);
} elseif (!first && before.size() != 1) { thrownew RuntimeException("Expected a single lock file! Found: " + before);
}
} finally {
before.stream().forEach(CheckZombieLockTest::delete);
}
FileHandler handler = createFileHandler(writableDir);
System.out.println("handler created: " + handler);
List<File> after = listLocks(writableDir, true);
System.out.println("after creating handler: " + after.size() + " locks found"); if (after.size() != 1) { thrownew RuntimeException("Unexpected number of lock files found for "
+ handler + ": " + after);
}
}
/** * Setup all the files and directories needed for the tests * * @return writable directory created that needs to be deleted when done * @throws RuntimeException
*/ privatestatic File setup() throws RuntimeException { // First do some setup in the temporary directory (using same logic as // FileHandler for %t pattern)
String tmpDir = System.getProperty("java.io.tmpdir"); // i.e. %t if (tmpDir == null) {
tmpDir = System.getProperty("user.home");
}
File tmpOrHomeDir = new File(tmpDir); // Create a writable directory here (%t/writable-lockfile-dir)
File writableDir = new File(tmpOrHomeDir, WRITABLE_DIR); if (!createFile(writableDir, true)) { thrownew RuntimeException("Test setup failed: unable to create"
+ " writable working directory "
+ writableDir.getAbsolutePath() );
}
// try to determine whether file locking is supported final String uniqueFileName = UUID.randomUUID().toString()+".lck"; try (FileChannel fc = FileChannel.open(Paths.get(writableDir.getAbsolutePath(),
uniqueFileName), CREATE_NEW, APPEND, DELETE_ON_CLOSE)) { try {
fc.tryLock();
} catch (IOException x) {
supportsLocking = false;
}
} catch (IOException t) { // should not happen
System.err.println("Failed to create new file " + uniqueFileName + " in " + writableDir.getAbsolutePath()); thrownew RuntimeException("Test setup failed: unable to run test", t);
} return writableDir;
}
/* * Recursively delete all files starting at specified file
*/ privatestaticvoiddelete(File f) { if (f != null && f.isDirectory()) { for (File c : f.listFiles()) delete(c);
} if (!f.delete())
System.err.println( "WARNING: unable to delete/cleanup writable test directory: "
+ f );
}
}
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.