Home | History | Annotate | Download | only in stacks
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.bugreport.stacks;
     18 
     19 import com.android.bugreport.util.Line;
     20 import com.android.bugreport.util.Lines;
     21 import com.android.bugreport.util.Utils;
     22 
     23 import java.io.BufferedReader;
     24 import java.io.IOException;
     25 import java.util.ArrayList;
     26 import java.util.regex.Pattern;
     27 import java.util.regex.Matcher;
     28 
     29 /**
     30  * Parse a vm traces process.
     31  *
     32  * The parser can be reused, but is not thread safe.
     33  */
     34 public class ProcessSnapshotParser {
     35     public static final Pattern BEGIN_PROCESS_RE = Pattern.compile(
     36                     "----- pid (\\d+) at (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) -----");
     37     private static final Pattern END_PROCESS_RE
     38             = Pattern.compile("----- end \\d+ -----");
     39 
     40     public static final Pattern CMD_LINE_RE = Pattern.compile(
     41                     "Cmd line: (.*)");
     42 
     43     /**
     44      * Construct a new parser.
     45      */
     46     public ProcessSnapshotParser() {
     47     }
     48 
     49     /**
     50      * Parse the given Lines until the beginning of the next process section, or until
     51      * the end of input is reached.
     52      */
     53     public ProcessSnapshot parse(Lines<? extends Line> lines) {
     54         final ProcessSnapshot result = new ProcessSnapshot();
     55 
     56         final Matcher beginProcessRe = BEGIN_PROCESS_RE.matcher("");
     57         final Matcher beginUnmanagedThreadRe = ThreadSnapshotParser.BEGIN_UNMANAGED_THREAD_RE
     58                 .matcher("");
     59         final Matcher beginManagedThreadRe = ThreadSnapshotParser.BEGIN_MANAGED_THREAD_RE
     60                 .matcher("");
     61         final Matcher beginNotAttachedThreadRe = ThreadSnapshotParser.BEGIN_NOT_ATTACHED_THREAD_RE
     62                 .matcher("");
     63         final Matcher endProcessRe = END_PROCESS_RE.matcher("");
     64         final Matcher cmdLineRe = CMD_LINE_RE.matcher("");
     65 
     66         final int STATE_INITIAL = 0;
     67         final int STATE_THREADS = 1;
     68         int state = STATE_INITIAL;
     69 
     70         // Preamble
     71         while (lines.hasNext()) {
     72             final Line line = lines.next();
     73             final String text = line.text;
     74             if (Utils.matches(beginProcessRe, text)) {
     75                 result.pid = Integer.parseInt(beginProcessRe.group(1));
     76                 result.date = beginProcessRe.group(2);
     77             } else if (Utils.matches(beginUnmanagedThreadRe, text)) {
     78                 state = STATE_THREADS;
     79                 lines.rewind();
     80                 break;
     81             } else if (Utils.matches(beginManagedThreadRe, text)) {
     82                 state = STATE_THREADS;
     83                 lines.rewind();
     84                 break;
     85             } else if (Utils.matches(beginNotAttachedThreadRe, text)) {
     86                 state = STATE_THREADS;
     87                 lines.rewind();
     88                 break;
     89             } else if (Utils.matches(endProcessRe, text)) {
     90                 break;
     91             } else if (Utils.matches(cmdLineRe, text)) {
     92                 result.cmdLine = cmdLineRe.group(1);
     93             } else {
     94                 if (false) {
     95                     System.out.println("ProcessSnapshotParser Dropping: " + text);
     96                 }
     97             }
     98         }
     99 
    100         // Thread list
    101         if (state == STATE_THREADS) {
    102             while (lines.hasNext()) {
    103                 final Line line = lines.next();
    104                 final String text = line.text;
    105                 if (Utils.matches(beginUnmanagedThreadRe, text)
    106                         || Utils.matches(beginManagedThreadRe, text)
    107                         || Utils.matches(beginNotAttachedThreadRe, text)) {
    108                     lines.rewind();
    109                     ThreadSnapshotParser parser = new ThreadSnapshotParser();
    110                     final ThreadSnapshot snapshot = parser.parse(lines);
    111                     if (snapshot != null) {
    112                         result.threads.add(snapshot);
    113                     } else {
    114                         // TODO: Try to backtrack and correct the parsing.
    115                     }
    116                 } else if (Utils.matches(endProcessRe, text)) {
    117                     break;
    118                 } else {
    119                     if (false) {
    120                         System.out.println("ProcessSnapshotParser STATE_THREADS Dropping: " + text);
    121                     }
    122                 }
    123             }
    124         }
    125 
    126         if (false) {
    127             System.out.println();
    128             System.out.println("PROCESS");
    129             System.out.println("pid=" + result.pid);
    130             System.out.println("date=" + result.date);
    131             System.out.println("threads=" + result.threads.size());
    132             System.out.println("cmdLine=" + result.cmdLine);
    133         }
    134 
    135         return result;
    136     }
    137 
    138 }
    139 
    140