View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.issue.lbcore258;
15  
16  import java.io.FileOutputStream;
17  import java.io.IOException;
18  import java.nio.channels.FileChannel;
19  import java.nio.channels.FileLock;
20  
21  /**
22   *  FileLockSimulator is a small application intended to simulate FileAppender in prudent mode.
23   * In this mode, the application obtains an exclusive lock on the file, writes to the file and
24   * then releases the lock.
25   *
26   * <pre>  Usage:
27   *   java  FileLockSimulator instanceName pathToLogFile delay
28   * where
29   * "instanceName" is the name given to the current instance of the application
30   * "pathToLogFile" is the path to the log file
31   * "delay" is the number of milliseconds of sleep observed every 128 writes
32   * </pre>
33   *
34   * <b>This small application requires only the JDK to compile and to execute.</b>
35   *
36   * <p>FileLockSimulator should be launched as many times and from as many hosts as there will be
37   * JVMs writing to a log file in prudent mode. Performance should be quite good if
38   * "pathToLogFile" is on a local file system. On networked file systems such as NFS, performance
39   * depends on the speed of the network and NFS implementation. It has been observed that file
40   * locking over NFS is biased so that the current owner of the lock is favored over other processes.
41   * Thus, while one process hogs the lock for the log file, other processes starve waiting for the
42   * lock to the point of appearing deadlocked.
43   *
44   */
45  public class FileLockSimulator {
46  
47      static String LINE_SEPARATOR = System.getProperty("line.separator");
48      static final int DOT_FREQ = 128;
49      static final int DOT_WITH_NEW_LINE_FREQ = DOT_FREQ * 80;
50  
51      static String instanceName;
52      static int delay;
53      static FileOutputStream fos;
54      static FileChannel fileChannel;
55  
56      public static void main(String[] args) throws IOException, InterruptedException {
57  
58          String instanceName = args[0];
59          System.out.println("Instance named as [" + instanceName + "]");
60  
61          String fileStr = args[1];
62          System.out.println("Output target specified as [" + fileStr + "]");
63  
64          int delay = Integer.parseInt(args[2]);
65          System.out.println("Sleep delay specified as [" + delay + "] milliseconds");
66  
67          fos = new FileOutputStream(fileStr, true);
68          fileChannel = fos.getChannel();
69  
70          for (int i = 1;; i++) {
71              printDotAndSleep(i);
72              lockAndWrite(i);
73          }
74      }
75  
76      static void lockAndWrite(int i) throws InterruptedException, IOException {
77          FileLock fileLock = null;
78          try {
79              fileLock = fileChannel.lock();
80              long position = fileChannel.position();
81              long size = fileChannel.size();
82              if (size != position) {
83                  fileChannel.position(size);
84              }
85              String msg = "hello from" + instanceName + " " + i + LINE_SEPARATOR;
86              fos.write(msg.getBytes());
87          } finally {
88              if (fileLock != null) {
89                  fileLock.release();
90              }
91          }
92      }
93  
94      static void printDotAndSleep(int i) throws InterruptedException {
95          if (i % DOT_FREQ == 0) {
96              System.out.print(".");
97              Thread.sleep(delay);
98          }
99          if (i % DOT_WITH_NEW_LINE_FREQ == 0)
100             System.out.println("");
101     }
102 }