1 /*
<lambda>null2  * 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.collections.SparseArray
20 import trebuchet.importers.ftrace.events.FtraceEvent
21 import trebuchet.model.InvalidId
22 import trebuchet.model.fragments.CpuModelFragment
23 import trebuchet.model.fragments.ModelFragment
24 import trebuchet.model.fragments.ProcessModelFragment
25 import trebuchet.model.fragments.ThreadModelFragment
26 
27 class FtraceImporterState {
28     private val pidMap = SparseArray<ThreadModelFragment>(50)
29     private val cpuMap = SparseArray<CpuModelFragment>(6)
30     val modelFragment = ModelFragment()
31 
32     fun finish(): ModelFragment {
33         return modelFragment
34     }
35 
36     fun importEvent(event: FtraceEvent) {
37         if (modelFragment.globalStartTime == 0.0) {
38             modelFragment.globalStartTime = event.timestamp
39         }
40         modelFragment.globalEndTime = event.timestamp
41         event.import(this)
42     }
43 
44     private fun createProcess(tgid: Int, name: String? = null): ThreadModelFragment {
45         val proc = ProcessModelFragment(tgid, name)
46         modelFragment.processes.add(proc)
47         val thread = proc.threadFor(tgid, name)
48         if (pidMap[tgid] != null) {
49             IllegalStateException("Unable to create process $tgid - already exists!")
50         }
51         pidMap.put(tgid, thread)
52         return thread
53     }
54 
55     fun processFor(tgid: Int, name: String? = null): ProcessModelFragment {
56         val thread = pidMap[tgid] ?: createProcess(tgid, name)
57         thread.process.hint(tgid, name)
58         return thread.process
59     }
60 
61     private fun createUnknownProcess(): ProcessModelFragment {
62         return ProcessModelFragment(InvalidId, hasIdCb = { process ->
63             val tgid = process.id
64             val existing = pidMap[tgid]
65             if (existing != null) {
66                 existing.process.merge(process)
67             } else {
68                 pidMap.put(tgid, process.threadFor(tgid, process.name))
69             }
70             if (modelFragment.processes.none { it.id == process.id }) {
71                 modelFragment.processes.add(process)
72             }
73         })
74     }
75 
76     fun threadFor(pid: Int, tgid: Int = InvalidId, task: String? = null): ThreadModelFragment {
77         var thread = pidMap[pid]
78         val processName = if (tgid == pid) task else null
79         if (thread != null) {
80             thread.hint(name = task, tgid = tgid, processName = processName)
81             return thread
82         }
83         val process =
84                 if (tgid != InvalidId) processFor(tgid)
85                 else createUnknownProcess()
86         thread = process.threadFor(pid, task)
87         thread.hint(processName = processName)
88         pidMap.put(pid, thread)
89         return thread
90     }
91 
92     fun threadFor(line: FtraceLine) = threadFor(line.pid, line.tgid, line.task)
93     fun threadFor(event: FtraceEvent) = threadFor(event.pid, event.tgid, event.task)
94 
95     fun cpuFor(cid: Int): CpuModelFragment {
96         var cpu = cpuMap[cid]
97         if (cpu == null) {
98             cpu = CpuModelFragment(cid)
99             modelFragment.cpus.add(cpu)
100         }
101         cpuMap.put(cid, cpu)
102         return cpuMap[cid]!!
103     }
104 }