001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.issue.lbcore258; 015 016import java.io.FileOutputStream; 017import java.io.IOException; 018import java.nio.channels.FileChannel; 019import java.nio.channels.FileLock; 020 021/** 022 * FileLockSimulator is a small application intended to simulate FileAppender in prudent mode. 023 * In this mode, the application obtains an exclusive lock on the file, writes to the file and 024 * then releases the lock. 025 * 026 * <pre> Usage: 027 * java FileLockSimulator instanceName pathToLogFile delay 028 * where 029 * "instanceName" is the name given to the current instance of the application 030 * "pathToLogFile" is the path to the log file 031 * "delay" is the number of milliseconds of sleep observed every 128 writes 032 * </pre> 033 * 034 * <b>This small application requires only the JDK to compile and to execute.</b> 035 * 036 * <p>FileLockSimulator should be launched as many times and from as many hosts as there will be 037 * JVMs writing to a log file in prudent mode. Performance should be quite good if 038 * "pathToLogFile" is on a local file system. On networked file systems such as NFS, performance 039 * depends on the speed of the network and NFS implementation. It has been observed that file 040 * locking over NFS is biased so that the current owner of the lock is favored over other processes. 041 * Thus, while one process hogs the lock for the log file, other processes starve waiting for the 042 * lock to the point of appearing deadlocked. 043 * 044 */ 045public class FileLockSimulator { 046 047 static String LINE_SEPARATOR = System.getProperty("line.separator"); 048 static final int DOT_FREQ = 128; 049 static final int DOT_WITH_NEW_LINE_FREQ = DOT_FREQ * 80; 050 051 static String instanceName; 052 static int delay; 053 static FileOutputStream fos; 054 static FileChannel fileChannel; 055 056 public static void main(String[] args) throws IOException, InterruptedException { 057 058 String instanceName = args[0]; 059 System.out.println("Instance named as [" + instanceName + "]"); 060 061 String fileStr = args[1]; 062 System.out.println("Output target specified as [" + fileStr + "]"); 063 064 int delay = Integer.parseInt(args[2]); 065 System.out.println("Sleep delay specified as [" + delay + "] milliseconds"); 066 067 fos = new FileOutputStream(fileStr, true); 068 fileChannel = fos.getChannel(); 069 070 for (int i = 1;; i++) { 071 printDotAndSleep(i); 072 lockAndWrite(i); 073 } 074 } 075 076 static void lockAndWrite(int i) throws InterruptedException, IOException { 077 FileLock fileLock = null; 078 try { 079 fileLock = fileChannel.lock(); 080 long position = fileChannel.position(); 081 long size = fileChannel.size(); 082 if (size != position) { 083 fileChannel.position(size); 084 } 085 String msg = "hello from" + instanceName + " " + i + LINE_SEPARATOR; 086 fos.write(msg.getBytes()); 087 } finally { 088 if (fileLock != null) { 089 fileLock.release(); 090 } 091 } 092 } 093 094 static void printDotAndSleep(int i) throws InterruptedException { 095 if (i % DOT_FREQ == 0) { 096 System.out.print("."); 097 Thread.sleep(delay); 098 } 099 if (i % DOT_WITH_NEW_LINE_FREQ == 0) 100 System.out.println(""); 101 } 102}