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
23   * prudent mode. In this mode, the application obtains an exclusive lock on the
24   * file, writes to the file and then releases the lock.
25   *
26   * <pre>
27   *   Usage:
28   *   java  FileLockSimulator instanceName pathToLogFile delay
29   * where
30   * "instanceName" is the name given to the current instance of the application
31   * "pathToLogFile" is the path to the log file
32   * "delay" is the number of milliseconds of sleep observed every 128 writes
33   * </pre>
34   *
35   * <b>This small application requires only the JDK to compile and to
36   * execute.</b>
37   *
38   * <p>
39   * FileLockSimulator should be launched as many times and from as many hosts as
40   * there will be JVMs writing to a log file in prudent mode. Performance should
41   * be quite good if "pathToLogFile" is on a local file system. On networked file
42   * systems such as NFS, performance depends on the speed of the network and NFS
43   * implementation. It has been observed that file locking over NFS is biased so
44   * that the current owner of the lock is favored over other processes. Thus,
45   * while one process hogs the lock for the log file, other processes starve
46   * waiting for the lock to the point of appearing deadlocked.
47   *
48   */
49  public class FileLockSimulator {
50  
51      static String LINE_SEPARATOR = System.getProperty("line.separator");
52      static final int DOT_FREQ = 128;
53      static final int DOT_WITH_NEW_LINE_FREQ = DOT_FREQ * 80;
54  
55      static String instanceName;
56      static int delay;
57      static FileOutputStream fos;
58      static FileChannel fileChannel;
59  
60      public static void main(String[] args) throws IOException, InterruptedException {
61  
62          String instanceName = args[0];
63          System.out.println("Instance named as [" + instanceName + "]");
64  
65          String fileStr = args[1];
66          System.out.println("Output target specified as [" + fileStr + "]");
67  
68          int delay = Integer.parseInt(args[2]);
69          System.out.println("Sleep delay specified as [" + delay + "] milliseconds");
70  
71          fos = new FileOutputStream(fileStr, true);
72          fileChannel = fos.getChannel();
73  
74          for (int i = 1;; i++) {
75              printDotAndSleep(i);
76              lockAndWrite(i);
77          }
78      }
79  
80      static void lockAndWrite(int i) throws InterruptedException, IOException {
81          FileLock fileLock = null;
82          try {
83              fileLock = fileChannel.lock();
84              long position = fileChannel.position();
85              long size = fileChannel.size();
86              if (size != position) {
87                  fileChannel.position(size);
88              }
89              String msg = "hello from" + instanceName + " " + i + LINE_SEPARATOR;
90              fos.write(msg.getBytes());
91          } finally {
92              if (fileLock != null) {
93                  fileLock.release();
94              }
95          }
96      }
97  
98      static void printDotAndSleep(int i) throws InterruptedException {
99          if (i % DOT_FREQ == 0) {
100             System.out.print(".");
101             Thread.sleep(delay);
102         }
103         if (i % DOT_WITH_NEW_LINE_FREQ == 0)
104             System.out.println("");
105     }
106 }