/** * Logback: the reliable, generic, fast and flexible logging framework. * Copyright (C) 1999-2015, QOS.ch. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */ package ch.qos.logback.core.issue.lbcore258; import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; /** * FileLockSimulator is a small application intended to simulate FileAppender in prudent mode. * In this mode, the application obtains an exclusive lock on the file, writes to the file and * then releases the lock. * * <pre> Usage: * java FileLockSimulator instanceName pathToLogFile delay * where * "instanceName" is the name given to the current instance of the application * "pathToLogFile" is the path to the log file * "delay" is the number of milliseconds of sleep observed every 128 writes * </pre> * * <b>This small application requires only the JDK to compile and to execute.</b> * * <p>FileLockSimulator should be launched as many times and from as many hosts as there will be * JVMs writing to a log file in prudent mode. Performance should be quite good if * "pathToLogFile" is on a local file system. On networked file systems such as NFS, performance * depends on the speed of the network and NFS implementation. It has been observed that file * locking over NFS is biased so that the current owner of the lock is favored over other processes. * Thus, while one process hogs the lock for the log file, other processes starve waiting for the * lock to the point of appearing deadlocked. * */ public class FileLockSimulator { static String LINE_SEPARATOR = System.getProperty("line.separator"); static final int DOT_FREQ = 128; static final int DOT_WITH_NEW_LINE_FREQ = DOT_FREQ * 80; static String instanceName; static int delay; static FileOutputStream fos; static FileChannel fileChannel; public static void main(String[] args) throws IOException, InterruptedException { String instanceName = args[0]; System.out.println("Instance named as [" + instanceName + "]"); String fileStr = args[1]; System.out.println("Output target specified as [" + fileStr + "]"); int delay = Integer.parseInt(args[2]); System.out.println("Sleep delay specified as [" + delay + "] milliseconds"); fos = new FileOutputStream(fileStr, true); fileChannel = fos.getChannel(); for (int i = 1;; i++) { printDotAndSleep(i); lockAndWrite(i); } } static void lockAndWrite(int i) throws InterruptedException, IOException { FileLock fileLock = null; try { fileLock = fileChannel.lock(); long position = fileChannel.position(); long size = fileChannel.size(); if (size != position) { fileChannel.position(size); } String msg = "hello from" + instanceName + " " + i + LINE_SEPARATOR; fos.write(msg.getBytes()); } finally { if (fileLock != null) { fileLock.release(); } } } static void printDotAndSleep(int i) throws InterruptedException { if (i % DOT_FREQ == 0) { System.out.print("."); Thread.sleep(delay); } if (i % DOT_WITH_NEW_LINE_FREQ == 0) System.out.println(""); } }