src/share/classes/java/util/logging/FileHandler.java

Print this page

        

*** 23,45 **** --- 23,51 ---- * questions. */ package java.util.logging; + import static java.nio.file.StandardOpenOption.APPEND; import static java.nio.file.StandardOpenOption.CREATE_NEW; import static java.nio.file.StandardOpenOption.WRITE; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.channels.FileChannel; + import java.nio.channels.OverlappingFileLockException; import java.nio.file.FileAlreadyExistsException; + import java.nio.file.Files; + import java.nio.file.Path; import java.nio.file.Paths; import java.security.AccessController; import java.security.PrivilegedAction; + import java.util.HashSet; + import java.util.Set; /** * Simple file logging <tt>Handler</tt>. * <p> * The <tt>FileHandler</tt> can either write to a specified file,
*** 147,157 **** private String pattern; private String lockFileName; private FileChannel lockFileChannel; private File files[]; private static final int MAX_LOCKS = 100; ! private static final java.util.HashMap<String, String> locks = new java.util.HashMap<>(); /** * A metered stream is a subclass of OutputStream that * (a) forwards all its output to a target stream * (b) keeps track of how many bytes have been written --- 153,163 ---- private String pattern; private String lockFileName; private FileChannel lockFileChannel; private File files[]; private static final int MAX_LOCKS = 100; ! private static final Set<String> locks = new HashSet<>(); /** * A metered stream is a subclass of OutputStream that * (a) forwards all its output to a target stream * (b) keeps track of how many bytes have been written
*** 426,463 **** // Now try to lock that filename. // Because some systems (e.g., Solaris) can only do file locks // between processes (and not within a process), we first check // if we ourself already have the file locked. synchronized(locks) { ! if (locks.get(lockFileName) != null) { // We already own this lock, for a different FileHandler // object. Try again. continue; } try { ! lockFileChannel = FileChannel.open(Paths.get(lockFileName), CREATE_NEW, WRITE); } catch (FileAlreadyExistsException ix) { // try the next lock file name in the sequence continue; } boolean available; try { available = lockFileChannel.tryLock() != null; // We got the lock OK. } catch (IOException ix) { // We got an IOException while trying to get the lock. // This normally indicates that locking is not supported // on the target directory. We have to proceed without ! // getting a lock. Drop through. ! available = true; } if (available) { // We got the lock. Remember it. ! locks.put(lockFileName, lockFileName); break; } // We failed to get the lock. Try next file. lockFileChannel.close(); --- 432,494 ---- // Now try to lock that filename. // Because some systems (e.g., Solaris) can only do file locks // between processes (and not within a process), we first check // if we ourself already have the file locked. synchronized(locks) { ! if (locks.contains(lockFileName)) { // We already own this lock, for a different FileHandler // object. Try again. continue; } + final Path lockFilePath = Paths.get(lockFileName); + boolean fileCreated; try { ! lockFileChannel = FileChannel.open(lockFilePath, CREATE_NEW, WRITE); + fileCreated = true; } catch (FileAlreadyExistsException ix) { + // This may be a zombie file left over by a previous + // execution. Reuse it - but only if we can actually + // write to its directory. + if (Files.isRegularFile(lockFilePath) + && Files.isWritable(lockFilePath) + && Files.isWritable(lockFilePath.getParent())) { + lockFileChannel = FileChannel.open(lockFilePath, + WRITE, APPEND); + fileCreated = false; + } else { // try the next lock file name in the sequence continue; } + } boolean available; try { available = lockFileChannel.tryLock() != null; // We got the lock OK. + // At this point we could call File.deleteOnExit(). + // However, this could have undesirable side effects + // as indicated by JDK-4872014. So we will instead + // rely on the fact that close() will remove the lock + // file and that whoever is creating FileHandlers should + // be responsible for closing them. } catch (IOException ix) { // We got an IOException while trying to get the lock. // This normally indicates that locking is not supported // on the target directory. We have to proceed without ! // getting a lock. Drop through, but only if we did ! // create the file... ! available = fileCreated; ! } catch (OverlappingFileLockException x) { ! // someone already locked this file in this VM. ! // continue searching for an available lock. ! available = false; } if (available) { // We got the lock. Remember it. ! locks.add(lockFileName); break; } // We failed to get the lock. Try next file. lockFileChannel.close();