• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Google Inc.
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  *     https://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 trebuchet.importers.ftrace
18 
19 import trebuchet.io.DataSlice
20 import trebuchet.io.asSlice
21 import trebuchet.model.InvalidId
22 import trebuchet.util.BufferReader
23 import trebuchet.util.StringCache
24 import java.util.regex.Matcher
25 import java.util.regex.Pattern
26 import kotlin.concurrent.getOrSet
27 
28 @Suppress("unused")
29 const val FtraceLineRE = """^*(.{1,16})-(\d+) +(?:\( *(\d+)?-*\) )?\[(\d+)] (?:[dX.]...)? *([\d.]*): *([^:]*): (.*)$"""
30 
31 class FtraceLine private constructor() {
32     private var _task: String? = null
33     private var _pid: Int = 0
34     private var _tgid: Int = 0
35     private var _cpu: Int = 0
36     private var _timestamp: Double = 0.0
37     private var _function: DataSlice = DataSlice()
38     private var _functionDetails: BufferReader? = null
39 
40     val hasTgid: Boolean get() = _tgid != InvalidId
41     var tgid: Int
42         get() = _tgid
43         set(value) {
44             if (hasTgid && _tgid != value) {
45                 throw IllegalStateException("tgid fight, currently $_tgid but trying to set $value")
46             }
47             _tgid = value
48         }
49     val task get() = _task
50     val pid get() = _pid
51     val cpu get() = _cpu
52     val timestamp get() = _timestamp
53     val function get() = _function
54     val functionDetailsReader get() = _functionDetails!!
55 
setnull56     private fun set(taskName: String?, pid: Int, tgid: Int, cpu: Int, timestamp: Double,
57                     func: DataSlice, funcDetails: BufferReader) {
58         _task = taskName
59         _pid = pid
60         _tgid = tgid
61         _cpu = cpu
62         _timestamp = timestamp
63         _function = func
64         _functionDetails = funcDetails
65     }
66 
67     companion object {
68         val INVALID_LINE = FtraceLine()
69 
70         private val matcherLocal = ThreadLocal<Matcher>()
71         private val readerLocal = ThreadLocal<BufferReader>()
72 
73         private val matcher: Matcher
<lambda>null74             get() = matcherLocal.getOrSet { Pattern.compile(FtraceLineRE).matcher("") }
75         private val reader: BufferReader
<lambda>null76             get() = readerLocal.getOrSet { BufferReader() }
77 
createnull78         fun create(line: DataSlice, stringCache: StringCache): FtraceLine? {
79             try {
80                 reader.read(line, stringCache) {
81                     tryMatch(matcher) {
82                         val ftraceLine = FtraceLine()
83                         ftraceLine.set(
84                                 string(1),
85                                 int(2),
86                                 if (matcher!!.start(3) == -1) InvalidId else int(3),
87                                 int(4),
88                                 double(5),
89                                 slice(6),
90                                 reader(7)
91                         )
92                         return@create ftraceLine
93                     }
94                 }
95             } catch (ex: Exception) {
96 
97             }
98             return null
99         }
100     }
101 
102     class Parser(val stringCache: StringCache) {
103         private val NullTaskName = stringCache.stringFor("<...>".asSlice())
104         private val ftraceLine = FtraceLine()
105         private val _reader = BufferReader()
106         private val matcher = Pattern.compile(FtraceLineRE).matcher("")
107 
parseLine_newnull108         fun parseLine_new(line: DataSlice, callback: (FtraceLine) -> Unit) =
109                 _reader.read(line, stringCache) {
110             match(matcher) {
111                 ftraceLine.set(
112                         string(1),
113                         int(2),
114                         if (matcher!!.start(3) == -1) InvalidId else int(3),
115                         int(4),
116                         double(5),
117                         slice(6),
118                         reader(7)
119                 )
120                 callback(ftraceLine)
121             }
122         }
123 
parseLinenull124         fun parseLine(line: DataSlice, callback: (FtraceLine) -> Unit) =
125                 _reader.read(line, stringCache) {
126             var tgid: Int = InvalidId
127             skipChar(' '.toByte())
128             val taskName = stringTo {
129                 skipUntil { it == '-'.toByte() }
130                 skipUntil { it == '('.toByte() || it == '['.toByte() }
131                 rewindUntil { it == '-'.toByte() }
132             }
133             val pid = readInt()
134             skipChar(' '.toByte())
135             if (peek() == '('.toByte()) {
136                 skip()
137                 if (peek() != '-'.toByte()) {
138                     tgid = readInt()
139                 }
140                 skipUntil { it == ')'.toByte() }
141             }
142             val cpu = readInt()
143             skipCount(2)
144             if (peek() == '.'.toByte() || peek() > '9'.toByte()) {
145                 skipCount(5)
146             }
147             skipChar(' '.toByte())
148             val timestamp = readDouble()
149             skipCount(1); skipChar(' '.toByte())
150             val func = sliceTo(ftraceLine.function) { skipUntil { it == ':'.toByte() } }
151             skipCount(1)
152             skipChar(' '.toByte())
153             ftraceLine.set(if (taskName === NullTaskName) null else taskName, pid, tgid, cpu,
154                     timestamp, func, _reader)
155             callback(ftraceLine)
156         }
157     }
158 }
159 
validnull160 fun FtraceLine.valid() = this !== FtraceLine.INVALID_LINE
161