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 }