1// Copyright (C) 2020 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import {Actions} from '../../common/actions'; 16import {NUM, NUM_NULL, STR} from '../../common/query_result'; 17import {fromNs, toNs} from '../../common/time'; 18import {globals} from '../../controller/globals'; 19import { 20 TrackController, 21 trackControllerRegistry, 22} from '../../controller/track_controller'; 23 24import {Config, Data, DEBUG_SLICE_TRACK_KIND} from './common'; 25 26class DebugSliceTrackController extends TrackController<Config, Data> { 27 static readonly kind = DEBUG_SLICE_TRACK_KIND; 28 29 async onReload() { 30 const rawResult = await this.query( 31 `select ifnull(max(depth), 1) as maxDepth from debug_slices`); 32 const maxDepth = rawResult.firstRow({maxDepth: NUM}).maxDepth; 33 globals.dispatch( 34 Actions.updateTrackConfig({id: this.trackId, config: {maxDepth}})); 35 } 36 37 async onBoundsChange(start: number, end: number, resolution: number): 38 Promise<Data> { 39 const queryRes = await this.query(`select 40 ifnull(id, -1) as id, 41 ifnull(name, '[null]') as name, 42 ts, 43 iif(dur = -1, (SELECT end_ts FROM trace_bounds) - ts, dur) as dur, 44 ifnull(depth, 0) as depth 45 from debug_slices 46 where (ts + dur) >= ${toNs(start)} and ts <= ${toNs(end)}`); 47 48 const numRows = queryRes.numRows(); 49 50 const slices: Data = { 51 start, 52 end, 53 resolution, 54 length: numRows, 55 strings: [], 56 sliceIds: new Float64Array(numRows), 57 starts: new Float64Array(numRows), 58 ends: new Float64Array(numRows), 59 depths: new Uint16Array(numRows), 60 titles: new Uint16Array(numRows), 61 isInstant: new Uint16Array(numRows), 62 isIncomplete: new Uint16Array(numRows), 63 }; 64 65 const stringIndexes = new Map<string, number>(); 66 function internString(str: string) { 67 let idx = stringIndexes.get(str); 68 if (idx !== undefined) return idx; 69 idx = slices.strings.length; 70 slices.strings.push(str); 71 stringIndexes.set(str, idx); 72 return idx; 73 } 74 75 const it = queryRes.iter( 76 {id: NUM, name: STR, ts: NUM_NULL, dur: NUM_NULL, depth: NUM}); 77 for (let row = 0; it.valid(); it.next(), row++) { 78 let sliceStart: number, sliceEnd: number; 79 if (it.ts === null || it.dur === null) { 80 sliceStart = sliceEnd = -1; 81 } else { 82 sliceStart = it.ts; 83 sliceEnd = sliceStart + it.dur; 84 } 85 slices.sliceIds[row] = it.id; 86 slices.starts[row] = fromNs(sliceStart); 87 slices.ends[row] = fromNs(sliceEnd); 88 slices.depths[row] = it.depth; 89 const sliceName = it.name; 90 slices.titles[row] = internString(sliceName); 91 slices.isInstant[row] = 0; 92 slices.isIncomplete[row] = 0; 93 } 94 95 return slices; 96 } 97} 98 99trackControllerRegistry.register(DebugSliceTrackController); 100