From 548de07a34100184a4d733701b8cbfe7ac691c21 Mon Sep 17 00:00:00 2001 From: rpatil Date: Wed, 20 Dec 2017 06:12:10 -0800 Subject: [PATCH] 8153955: increase java.util.logging.FileHandler MAX_LOCKS limit Summary: This patch adds a new JDK implementation specific system property "jdk.internal.FileHandlerLogging.maxLocks" to control java.util.logging.FileHandler's MAX_LOCKS limit. Reviewed-by: coffeys, dfuchs --- .../java/util/logging/FileHandler.java | 27 ++++- .../util/logging/FileHandlerMaxLocksTest.java | 113 ++++++++++++++++++ 2 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 test/java/util/logging/FileHandlerMaxLocksTest.java diff --git a/src/share/classes/java/util/logging/FileHandler.java b/src/share/classes/java/util/logging/FileHandler.java index 2c3bb5025..8797622cf 100644 --- a/src/share/classes/java/util/logging/FileHandler.java +++ b/src/share/classes/java/util/logging/FileHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -156,9 +156,27 @@ public class FileHandler extends StreamHandler { private String lockFileName; private FileChannel lockFileChannel; private File files[]; - private static final int MAX_LOCKS = 100; + private static final int DEFAULT_MAX_LOCKS = 100; + private static int maxLocks; private static final Set locks = new HashSet<>(); + /* + * Initialize maxLocks from the System property if set. + * If invalid/no property is provided 100 will be used as a default value. + */ + static { + maxLocks = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> + Integer.getInteger( + "jdk.internal.FileHandlerLogging.maxLocks", + DEFAULT_MAX_LOCKS) + ); + + if (maxLocks <= 0) { + maxLocks = DEFAULT_MAX_LOCKS; + } + } + /** * A metered stream is a subclass of OutputStream that * (a) forwards all its output to a target stream @@ -434,8 +452,9 @@ public class FileHandler extends StreamHandler { int unique = -1; for (;;) { unique++; - if (unique > MAX_LOCKS) { - throw new IOException("Couldn't get lock for " + pattern); + if (unique > maxLocks) { + throw new IOException("Couldn't get lock for " + pattern + + ", maxLocks: " + maxLocks); } // Generate a lock file name from the "unique" int. lockFileName = generate(pattern, 0, unique).toString() + ".lck"; diff --git a/test/java/util/logging/FileHandlerMaxLocksTest.java b/test/java/util/logging/FileHandlerMaxLocksTest.java new file mode 100644 index 000000000..f184daf98 --- /dev/null +++ b/test/java/util/logging/FileHandlerMaxLocksTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017, 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. + */ + + /* + * @test + * @bug 8161266 + * @summary test the FileHandler's new System property + * "jdk.internal.FileHandlerLogging.maxLocks" with default value of 100. + * @library /lib/testlibrary + * @build jdk.testlibrary.FileUtils + * @author rpatil + * @run main/othervm -Djdk.internal.FileHandlerLogging.maxLocks=200 FileHandlerMaxLocksTest + * @run main/othervm -Djdk.internal.FileHandlerLogging.maxLocks=200ab FileHandlerMaxLocksTest + */ +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.FileHandler; +import jdk.testlibrary.FileUtils; + +public class FileHandlerMaxLocksTest { + + private static final String LOGGER_DIR = "logger-dir"; + private static final String MX_LCK_SYS_PROPERTY = + "jdk.internal.FileHandlerLogging.maxLocks"; + + public static void main(String[] args) throws Exception { + String maxLocksSet = System.getProperty(MX_LCK_SYS_PROPERTY); + File loggerDir = createLoggerDir(); + List fileHandlers = new ArrayList<>(); + try { + // 200 raises the default limit of 100, we try 102 times + for (int i = 0; i < 102; i++) { + fileHandlers.add(new FileHandler(loggerDir.getPath() + + File.separator + "test_%u.log")); + } + } catch (IOException ie) { + if (maxLocksSet.equals("200ab") + && ie.getMessage().contains("get lock for")) { + // Ignore: Expected exception while passing bad value- 200ab + } else { + throw new RuntimeException("Test Failed: " + ie.getMessage()); + } + } finally { + for (FileHandler fh : fileHandlers) { + fh.close(); + } + FileUtils.deleteFileTreeWithRetry(Paths.get(loggerDir.getPath())); + } + } + + /** + * Create a writable directory in user directory for the test + * + * @return writable directory created that needs to be deleted when done + * @throws RuntimeException + */ + private static File createLoggerDir() throws RuntimeException { + String userDir = System.getProperty("user.dir", "."); + File loggerDir = new File(userDir, LOGGER_DIR); + if (!createFile(loggerDir, true)) { + throw new RuntimeException("Test failed: unable to create" + + " writable working directory " + + loggerDir.getAbsolutePath()); + } + // System.out.println("Created Logger Directory: " + loggerDir.getPath()); + return loggerDir; + } + + /** + * @param newFile File to be created + * @param makeDirectory is File to be created is directory + * @return true if file already exists or creation succeeded + */ + private static boolean createFile(File newFile, boolean makeDirectory) { + if (newFile.exists()) { + return true; + } + if (makeDirectory) { + return newFile.mkdir(); + } else { + try { + return newFile.createNewFile(); + } catch (IOException ie) { + System.err.println("Not able to create file: " + newFile + + ", IOException: " + ie.getMessage()); + return false; + } + } + } +} -- GitLab