Author: thomasm
Date: Fri Jul  1 12:15:54 2016
New Revision: 1750920

URL: http://svn.apache.org/viewvc?rev=1750920&view=rev
Log:
OAK-4521 Oak-run: add profiling and analysis tools

Added:
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/ThreadDumpCleaner.java
Modified:
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/util/Profiler.java
    
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/util/Profiler.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/util/Profiler.java?rev=1750920&r1=1750919&r2=1750920&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/util/Profiler.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/util/Profiler.java
 Fri Jul  1 12:15:54 2016
@@ -17,13 +17,16 @@
 package org.apache.jackrabbit.oak.benchmark.util;
 
 import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.LineNumberReader;
 import java.io.OutputStream;
+import java.io.Reader;
 import java.io.StringReader;
-import java.util.ArrayList;
 import java.lang.instrument.Instrumentation;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -32,26 +35,38 @@ import java.util.Map;
 /**
  * A simple CPU profiling tool similar to java -Xrunhprof. It can be used
  * in-process (to profile the current application) or as a standalone program
- * (to profile a different process).
+ * (to profile a different process, or files containing full thread dumps).
  */
 public class Profiler implements Runnable {
 
     private static Instrumentation instrumentation;
-    private static final String LINE_SEPARATOR = 
System.getProperty("line.separator", "\n");
+    private static final String LINE_SEPARATOR =
+            System.getProperty("line.separator", "\n");
     private static final int MAX_ELEMENTS = 1000;
 
     public int interval = 2;
     public int depth = 48;
     public boolean paused;
     public boolean sumClasses;
+    public boolean sumMethods;
 
     private int pid;
 
-    private final String[] ignoreLines = {};
+    private final String[] ignoreLines = (
+            "java," +
+            "sun," +
+            "com.sun.," +
+            "com.google.common.," +
+            "com.mongodb.," +
+            "org.bson.,"
+            ).split(",");
     private final String[] ignorePackages = (
             "java," +
             "sun," +
-            "com.sun."
+            "com.sun.," +
+            "com.google.common.," +
+            "com.mongodb.," +
+            "org.bson"
             ).split(",");
     private final String[] ignoreThreads = (
             "java.lang.Object.wait," +
@@ -59,29 +74,37 @@ public class Profiler implements Runnabl
             "java.lang.Thread.getThreads," +
             "java.lang.Thread.sleep," +
             "java.lang.UNIXProcess.waitForProcessExit," +
+            "java.net.PlainDatagramSocketImpl.receive0," +
             "java.net.PlainSocketImpl.accept," +
             "java.net.PlainSocketImpl.socketAccept," +
             "java.net.SocketInputStream.socketRead," +
             "java.net.SocketOutputStream.socketWrite," +
+            "org.eclipse.jetty.io.nio.SelectorManager$SelectSet.doSelect," +
             "sun.awt.windows.WToolkit.eventLoop," +
             "sun.misc.Unsafe.park," +
+            "sun.nio.ch.EPollArrayWrapper.epollWait," +
+            "sun.nio.ch.KQueueArrayWrapper.kevent0," +
+            "sun.nio.ch.ServerSocketChannelImpl.accept," +
             "dalvik.system.VMStack.getThreadStackTrace," +
             "dalvik.system.NativeStart.run"
             ).split(",");
 
     private volatile boolean stop;
-    private final HashMap<String, Integer> counts = new HashMap<String, 
Integer>();
+    private final HashMap<String, Integer> counts =
+            new HashMap<String, Integer>();
 
     /**
      * The summary (usually one entry per package, unless sumClasses is 
enabled,
      * in which case it's one entry per class).
      */
-    private final HashMap<String, Integer> summary = new HashMap<String, 
Integer>();
+    private final HashMap<String, Integer> summary =
+            new HashMap<String, Integer>();
     private int minCount = 1;
     private int total;
     private Thread thread;
     private long start;
     private long time;
+    private int threadDumps;
 
     /**
      * This method is called when the agent is installed.
@@ -116,24 +139,67 @@ public class Profiler implements Runnabl
     private void run(String... args) {
         if (args.length == 0) {
             System.out.println("Show profiling data");
-            System.out.println("Usage: java " + getClass().getName() + " 
<pid>");
+            System.out.println("Usage: java " + getClass().getName() +
+                    " <pid> | <stackTraceFileNames>");
             System.out.println("Processes:");
             String processes = exec("jps", "-l");
             System.out.println(processes);
             return;
         }
-        pid = Integer.parseInt(args[0]);
         start = System.currentTimeMillis();
-        long last = 0;
-        while (true) {
-            tick();
-            long t = System.currentTimeMillis();
-            if (t - last > 5000) {
-                time = System.currentTimeMillis() - start;
-                System.out.println(getTopTraces(3));
-                last = t;
+        if (args[0].matches("\\d+")) {
+            pid = Integer.parseInt(args[0]);
+            long last = 0;
+            while (true) {
+                tick();
+                long t = System.currentTimeMillis();
+                if (t - last > 5000) {
+                    time = System.currentTimeMillis() - start;
+                    System.out.println(getTopTraces(3));
+                    last = t;
+                }
             }
         }
+        try {
+            for (String arg : args) {
+                if (arg.startsWith("-")) {
+                    if ("-classes".equals(arg)) {
+                        sumClasses = true;
+                    } else if ("-methods".equals(arg)) {
+                        sumMethods = true;
+                    } else if ("-packages".equals(arg)) {
+                        sumClasses = false;
+                        sumMethods = false;
+                    } else {
+                        throw new IllegalArgumentException(arg);
+                    }
+                    continue;
+                }
+                String file = arg;
+                Reader reader;
+                LineNumberReader r;
+                reader = new InputStreamReader(
+                        new FileInputStream(file), "CP1252");
+                r = new LineNumberReader(reader);
+                while (true) {
+                    String line = r.readLine();
+                    if (line == null) {
+                        break;
+                    } else if (line.startsWith("Full thread dump")) {
+                        threadDumps++;
+                    }
+                }
+                reader.close();
+                reader = new InputStreamReader(
+                        new FileInputStream(file), "CP1252");
+                r = new LineNumberReader(reader);
+                processList(readStackTrace(r));
+                reader.close();
+            }
+            System.out.println(getTopTraces(5));
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     private static List<Object[]> getRunnableStackTraces() {
@@ -154,52 +220,58 @@ public class Profiler implements Runnabl
     }
 
     private static List<Object[]> readRunnableStackTraces(int pid) {
-        ArrayList<Object[]> list = new ArrayList<Object[]>();
         try {
             String jstack = exec("jstack", "" + pid);
-            LineNumberReader r = new LineNumberReader(new 
StringReader(jstack));
+            LineNumberReader r = new LineNumberReader(
+                    new StringReader(jstack));
+            return readStackTrace(r);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static List<Object[]> readStackTrace(LineNumberReader r)
+            throws IOException {
+        ArrayList<Object[]> list = new ArrayList<Object[]>();
+        while (true) {
+            String line = r.readLine();
+            if (line == null) {
+                break;
+            }
+            if (!line.startsWith("\"")) {
+                // not a thread
+                continue;
+            }
+            line = r.readLine();
+            if (line == null) {
+                break;
+            }
+            line = line.trim();
+            if (!line.startsWith("java.lang.Thread.State: RUNNABLE")) {
+                continue;
+            }
+            ArrayList<String> stack = new ArrayList<String>();
             while (true) {
-                String line = r.readLine();
-                if (line == null) {
-                    break;
-                }
-                if (!line.startsWith("\"")) {
-                    // not a thread
-                    continue;
-                }
                 line = r.readLine();
                 if (line == null) {
                     break;
                 }
                 line = line.trim();
-                if (!line.startsWith("java.lang.Thread.State: RUNNABLE")) {
+                if (line.startsWith("- ")) {
                     continue;
                 }
-                ArrayList<String> stack = new ArrayList<String>();
-                while (true) {
-                    line = r.readLine();
-                    if (line == null) {
-                        break;
-                    }
-                    line = line.trim();
-                    if (line.startsWith("- ")) {
-                        continue;
-                    }
-                    if (!line.startsWith("at ")) {
-                        break;
-                    }
-                    line = line.substring(3).trim();
-                    stack.add(line);
-                }
-                if (stack.size() > 0) {
-                    String[] s = stack.toArray(new String[stack.size()]);
-                    list.add(s);
+                if (!line.startsWith("at ")) {
+                    break;
                 }
+                line = line.substring(3).trim();
+                stack.add(line);
+            }
+            if (stack.size() > 0) {
+                String[] s = stack.toArray(new String[stack.size()]);
+                list.add(s);
             }
-            return list;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
         }
+        return list;
     }
 
     private static String exec(String... args) {
@@ -221,7 +293,8 @@ public class Profiler implements Runnabl
         }
     }
 
-    private static void copyInThread(final InputStream in, final OutputStream 
out) {
+    private static void copyInThread(final InputStream in,
+            final OutputStream out) {
         new Thread("Profiler stream copy") {
             @Override
             public void run() {
@@ -238,7 +311,7 @@ public class Profiler implements Runnabl
                     throw new RuntimeException(e);
                 }
             }
-        }.run();
+        }.start();
     }
 
     /**
@@ -302,6 +375,11 @@ public class Profiler implements Runnabl
         } else {
             list = getRunnableStackTraces();
         }
+        threadDumps++;
+        processList(list);
+    }
+
+    private void processList(List<Object[]> list) {
         for (Object[] dump : list) {
             if (startsWithAny(dump[0].toString(), ignoreThreads)) {
                 continue;
@@ -331,6 +409,10 @@ public class Profiler implements Runnabl
                             int m = el.indexOf('.', index + 1);
                             index = m >= 0 ? m : index;
                         }
+                        if (sumMethods) {
+                            int m = el.indexOf('(', index + 1);
+                            index = m >= 0 ? m : index;
+                        }
                         String groupName = el.substring(0, index);
                         increment(summary, groupName, 0);
                     }
@@ -353,7 +435,8 @@ public class Profiler implements Runnabl
         return false;
     }
 
-    private static int increment(HashMap<String, Integer> map, String trace, 
int minCount) {
+    private static int increment(HashMap<String, Integer> map, String trace,
+            int minCount) {
         Integer oldCount = map.get(trace);
         if (oldCount == null) {
             map.put(trace, 1);
@@ -361,7 +444,8 @@ public class Profiler implements Runnabl
             map.put(trace, oldCount + 1);
         }
         while (map.size() > MAX_ELEMENTS) {
-            for (Iterator<Map.Entry<String, Integer>> ei = 
map.entrySet().iterator(); ei.hasNext();) {
+            for (Iterator<Map.Entry<String, Integer>> ei =
+                    map.entrySet().iterator(); ei.hasNext();) {
                 Map.Entry<String, Integer> e = ei.next();
                 if (e.getValue() <= minCount) {
                     ei.remove();
@@ -387,8 +471,14 @@ public class Profiler implements Runnabl
 
     private String getTopTraces(int count) {
         StringBuilder buff = new StringBuilder();
-        buff.append("Profiler: top ").append(count).append(" stack trace(s) of 
").append(time).
-            append(" ms:").append(LINE_SEPARATOR);
+        buff.append("Profiler: top ").append(count).append(" stack trace(s) of 
");
+        if (time > 0) {
+            buff.append(" of ").append(time).append(" ms");
+        }
+        if (threadDumps > 0) {
+            buff.append(" of ").append(threadDumps).append(" thread dumps");
+        }
+        buff.append(":").append(LINE_SEPARATOR);
         if (counts.size() == 0) {
             buff.append("(none)").append(LINE_SEPARATOR);
         }
@@ -401,7 +491,8 @@ public class Profiler implements Runnabl
         return buff.toString();
     }
 
-    private static void appendTop(StringBuilder buff, HashMap<String, Integer> 
map, int count, int total, boolean table) {
+    private static void appendTop(StringBuilder buff,
+            HashMap<String, Integer> map, int count, int total, boolean table) 
{
         for (int x = 0, min = 0;;) {
             int highest = 0;
             Map.Entry<String, Integer> best = null;

Modified: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java?rev=1750920&r1=1750919&r2=1750920&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Mode.java
 Fri Jul  1 12:15:54 2016
@@ -44,6 +44,7 @@ enum Mode {
     DUMPDATASTOREREFS("dumpdatastorerefs", new DataStoreCheckCommand()),
     RESETCLUSTERID("resetclusterid", new ResetClusterIdCommand()),
     PERSISTENTCACHE("persistentcache", new PersistentCacheCommand()),
+    THREADDUMP("threaddump", new ThreadDumpCommand()),
     HELP("help", new HelpCommand());
 
     private final String name;

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java?rev=1750920&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/ThreadDumpCommand.java
 Fri Jul  1 12:15:54 2016
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.run;
+
+import static java.util.Arrays.asList;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+
+import org.apache.jackrabbit.oak.benchmark.util.Profiler;
+import org.apache.jackrabbit.oak.threadDump.ThreadDumpCleaner;
+
+public class ThreadDumpCommand implements Command {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void execute(String... args) throws Exception {
+        OptionParser parser = new OptionParser();
+        OptionSpec<Void> filterSpec = parser.accepts("filter", 
+                "filter the thread dumps, only keep working threads");
+        OptionSpec<Void> profileSpec = parser.accepts("profile", 
+                "profile the thread dumps");
+        OptionSpec<Void> profileClassesSpec = parser.accepts("profileClasses", 
+                "profile classes");
+        OptionSpec<Void> profileMethodsSpec = parser.accepts("profileMethods", 
+                "profile methods");
+        OptionSpec<Void> profilePackagesSpec = 
parser.accepts("profilePackages", 
+                "profile packages");
+        OptionSpec<?> helpSpec = parser.acceptsAll(
+                asList("h", "?", "help"), "show help").forHelp();
+        OptionSet options = parser.parse(args);
+        parser.nonOptions(
+                "file or directory containing thread 
dumps").ofType(File.class);
+        if (options.has(helpSpec)
+                || options.nonOptionArguments().isEmpty()) {
+            System.out.println("Mode: " + Mode.THREADDUMP);
+            System.out.println();
+            parser.printHelpOn(System.out);
+            return;
+        }
+        boolean filter = options.has(filterSpec);
+        boolean profile = options.has(profileSpec);
+        boolean profileClasses = options.has(profileClassesSpec);
+        boolean profileMethods = options.has(profileMethodsSpec);
+        boolean profilePackages = options.has(profilePackagesSpec);
+        for (String fileName : ((List<String>) options.nonOptionArguments())) {
+            File file = new File(fileName);
+            if (file.isDirectory() || file.getName().endsWith(".gz")) {
+                file = combineAndExpandFiles(file);
+                System.out.println("Combined into " + file.getAbsolutePath());
+            }
+            if (filter) {
+                file = ThreadDumpCleaner.process(file);
+                System.out.println("Filtered into " + file.getAbsolutePath());
+            }
+            if (profile) {
+                ArrayList<String> list = new ArrayList<String>();
+                if (profileClasses) {
+                    list.add("-classes");
+                }
+                if (profileMethods) {
+                    list.add("-methods");
+                }                
+                if (profilePackages) {
+                    list.add("-packages");
+                }                
+                list.add(file.getAbsolutePath());
+                Profiler.main(list.toArray(new String[0]));
+            }
+        }
+    }
+    
+    private static File combineAndExpandFiles(File file) throws IOException {
+        if (!file.exists() || !file.isDirectory()) {
+            if (!file.getName().endsWith(".gz")) {
+                return file;
+            }
+        }
+        File target = new File(file.getParentFile(), file.getName() + ".txt");
+        PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(
+                target)));
+        try {
+            int count = processFileOrDirectory(file, writer);
+            System.out.println("    (total " + count + " full thread dumps)");
+        } finally {
+            writer.close();
+        }
+        return target;
+    }
+    
+    private static int processFileOrDirectory(File file, PrintWriter writer)
+            throws IOException {
+        if (file.isFile()) {
+            return processFile(file, writer);
+        }
+        int count = 0;
+        File[] list = file.listFiles();
+        if (list != null) {
+            for(File f : list) {
+                count += processFileOrDirectory(f, writer);
+            }
+        }
+        return count;
+    }
+    
+    private static int processFile(File file, PrintWriter writer) throws 
IOException {
+        Reader reader = null;
+        int count = 0;
+        try {
+            if (file.getName().endsWith(".DS_Store")) {
+                return 0;
+            }
+            int fullThreadDumps = 0;
+            if (file.getName().endsWith(".gz")) {
+                System.out.println("Extracting " + file.getAbsolutePath());
+                InputStream fileStream = new FileInputStream(file);
+                InputStream gzipStream = new GZIPInputStream(fileStream);
+                reader = new InputStreamReader(gzipStream);                
+            } else {
+                System.out.println("Reading " + file.getAbsolutePath());
+                reader = new FileReader(file);
+            }
+            LineNumberReader in = new LineNumberReader(new BufferedReader(
+                    reader));
+            while (true) {
+                String s;
+                try {
+                    s = in.readLine();
+                } catch (EOFException e) {
+                    // EOFException: Unexpected end of ZLIB input stream
+                    break;
+                }
+                if (s == null) {
+                    break;
+                }          
+                if (s.startsWith("Full thread dump")) {
+                    fullThreadDumps++;
+                }
+                writer.println(s);
+            }
+            if (fullThreadDumps > 0) {
+                count++;
+                System.out.println("    (contains " + fullThreadDumps + " full 
thread dumps)");
+            }
+        } finally {
+            if(reader != null) {
+                reader.close();
+            }
+        }
+        return count;
+    }    
+
+}

Added: 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/ThreadDumpCleaner.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/ThreadDumpCleaner.java?rev=1750920&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/ThreadDumpCleaner.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/threadDump/ThreadDumpCleaner.java
 Fri Jul  1 12:15:54 2016
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.threadDump;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+/**
+ * A tool that removes uninteresting lines from stack traces.
+ */
+public class ThreadDumpCleaner {
+
+    private static final String[] PATTERN_ARRAY = {
+        "\"Concurrent Mark-Sweep GC Thread\".*\n",
+
+        "\"Exception Catcher Thread\".*\n",
+
+        "JNI global references:.*\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\n",
+
+        "\".*?\".*\n\n",
+
+        "\\$\\$YJP\\$\\$",
+
+        "\"(Attach|Service|VM|GC|DestroyJavaVM|Signal|AWT|AppKit|C2 |Low Mem|" 
+
+                "process reaper|YJPAgent-).*?\"(?s).*?\n\n",
+
+        "   Locked ownable synchronizers:(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State: (TIMED_)?WAITING(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at sun.nio.ch.KQueueArrayWrapper.kevent0(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.io.FileInputStream.readBytes(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at sun.nio.ch.ServerSocketChannelImpl.accept(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.net.DualStackPlainSocketImpl.accept0(?s).*\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at sun.nio.ch.EPollArrayWrapper.epollWait(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.lang.Object.wait(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.net.PlainSocketImpl.socketAccept(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.net.SocketInputStream.socketRead0(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at 
sun.nio.ch.WindowsSelectorImpl\\$SubSelector.poll0(?s).*?\n\n",
+                
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at sun.management.ThreadImpl.dumpThreads0(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at sun.misc.Unsafe.park(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.net.PlainSocketImpl.socketClose0(?s).*?\n\n",
+
+        "\".*?\".*?\n   java.lang.Thread.State:.*\n\t" +
+                "at java.net.PlainSocketImpl.socketAvailable(?s).*?\n\n",
+
+        "<EndOfDump>\n\n",
+
+    };
+
+    private static ArrayList<Pattern> PATTERNS = new ArrayList<Pattern>();
+
+    static {
+        for (String s : PATTERN_ARRAY) {
+            PATTERNS.add(Pattern.compile(s));
+        }
+    }
+    
+    public static File process(File file) throws IOException {
+        String fileName = file.getName();
+        if (fileName.endsWith(".txt")) {
+            fileName = fileName.substring(0, fileName.length() - 
".txt".length());
+        }
+        File target = new File(file.getParentFile(), fileName + 
".filtered.txt");
+        PrintWriter writer = new PrintWriter(new BufferedWriter(
+                new FileWriter(target)));       
+        try {
+            processFile(file, writer);
+        } finally {
+            writer.close();
+        }
+        return target;
+    }
+    
+    private static void processFile(File file, PrintWriter writer) throws 
IOException {
+        LineNumberReader r = new LineNumberReader(new BufferedReader(
+                new FileReader(file)));
+        try {
+            process(r, writer);
+        } finally {
+            r.close();
+        }
+    }
+
+    private static void process(LineNumberReader reader, PrintWriter writer) 
throws IOException {
+        StringBuilder buff = new StringBuilder();
+        while (true) {
+            String line = reader.readLine();
+            if (line == null) {
+                break;
+            }
+            buff.append(line).append('\n');
+            if (line.trim().length() == 0) {
+                writer.print(filter(buff.toString()));
+                buff = new StringBuilder();
+            }
+        }
+        writer.println(filter(buff.toString()));
+    }
+
+    private static String filter(String s) {
+        for (Pattern p : PATTERNS) {
+            s = p.matcher(s).replaceAll("");
+        }
+        return s;
+    }
+
+}


Reply via email to