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.model.fragments 18 19 import trebuchet.model.InvalidId 20 import trebuchet.model.hasCount 21 22 class ProcessModelFragment(id: Int, var name: String? = null, 23 private var hasIdCb: ((trebuchet.model.fragments.ProcessModelFragment) -> Unit)? = null) { 24 private var _id: Int = id 25 var id: Int 26 get() = _id 27 set(value) { 28 _id = value 29 if (_id != InvalidId) { 30 hasIdCb?.invoke(this) 31 hasIdCb = null 32 } 33 } 34 35 private val _threads = mutableMapOf<Int, ThreadModelFragment>() 36 private val _counters = mutableMapOf<String, CounterFragment>() 37 38 val threads: Collection<ThreadModelFragment> get() = _threads.values 39 val counters: Map<String, CounterFragment> get() = _counters 40 val asyncSlicesBuilder = AsyncSlicesBuilder() 41 val asyncSlices: List<AsyncSlice> get() { 42 if (asyncSlicesBuilder.openSlices.isNotEmpty()) { 43 throw IllegalStateException("AsyncSlicesBuilder has open slices, not finished"); 44 } 45 return asyncSlicesBuilder.asyncSlices 46 } 47 48 fun threadFor(pid: Int, name: String? = null): ThreadModelFragment { 49 var thread = _threads[pid] 50 if (thread == null) { 51 thread = ThreadModelFragment(pid, this, name) 52 _threads.put(pid, thread) 53 } else { 54 thread.hint(name = name) 55 } 56 return thread 57 } 58 59 fun addCounterSample(name: String, timestamp: Double, value: Long) { 60 _counters.getOrPut(name, { CounterFragment(name) }).events.add(timestamp hasCount value) 61 } 62 63 fun merge(other: trebuchet.model.fragments.ProcessModelFragment) { 64 if (other === this) return 65 if (id != -1 && id != other.id) { 66 throw IllegalArgumentException("Process ID mismatch") 67 } 68 hint(name = other.name) 69 other._threads.forEach { (key, value) -> 70 if (_threads.put(key, value) != null) { 71 throw IllegalStateException("Unable to merge threads of the same ID $key") 72 } 73 value.process = this 74 } 75 other._counters.forEach { (key, value) -> 76 val existing = _counters.put(key, value) 77 if (existing != null) { 78 _counters[key]!!.events.addAll(existing.events) 79 } 80 } 81 } 82 83 fun hint(id: Int = InvalidId, name: String? = null) { 84 if (this.id == InvalidId) this.id = id 85 if (this.name == null) this.name = name 86 } 87 }