1// Copyright (c) 2021 Huawei Device Co., Ltd.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6//     http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14import { TraficEnum } from './utils/QueryEnum';
15import { clockList, hangList } from './utils/AllMemoryCache';
16import { Args } from './CommonArgs';
17
18export const chartHangDataSql = (args: Args): string => `
19SELECT
20  c.id as id,
21  c.ts - r.start_ts as startNS,
22  c.dur as dur,
23  t.tid as tid,
24  t.name as tname,
25  p.pid as pid,
26  p.name as pname
27FROM
28  callstack c, trace_range r
29LEFT JOIN thread t ON
30  t.itid = c.callid
31LEFT JOIN process p ON
32  p.ipid = t.ipid
33WHERE
34  c.dur >= ${args.minDur}
35  AND c.name LIKE 'H:Et:%'
36  AND t.is_main_thread = 1
37  AND p.pid = ${args.pid}
38`.trim();
39
40export interface HangSQLStruct {
41  id: number;
42  startNS: number;
43  dur: number;
44  tid: number;
45  pid: number;
46}
47
48export function hangDataReceiver(data: unknown, proc: Function): void {
49  // @ts-ignore
50  if (data.params.trafic === TraficEnum.Memory) {
51    let res: HangSQLStruct[];
52    let list: HangSQLStruct[];
53
54    // @ts-ignore
55    if (!hangList.has(data.params.pid)) {
56      // @ts-ignore
57      let sql = chartHangDataSql(data.params);
58      list = proc(sql);
59      // @ts-ignore
60      hangList.set(data.params.pid, list);
61    }
62    else {
63      // @ts-ignore
64      list = hangList.get(data.params.pid) || [];
65    }
66
67    // @ts-ignore
68    if (data.params.queryAll) {
69      res = list.filter(
70        //@ts-ignore
71        (it) => it.startNS + it.dur >= data.params.selectStartNS && it.startNS <= data.params.selectEndNS
72      );
73    }
74    else {
75      res = list;
76    }
77
78    arrayBufferHandler(data, res, true);
79  }
80  else {
81    // @ts-ignore
82    let sql = chartHangDataSql(data.params);
83    let res: HangSQLStruct[] = proc(sql);
84    // @ts-ignore
85    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer);
86  }
87}
88
89function arrayBufferHandler(data: unknown, res: HangSQLStruct[], transfer: boolean = true): void {
90  // @ts-ignore
91  let id = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.id);
92  // @ts-ignore
93  let startNS = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNS);
94  // @ts-ignore
95  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur);
96  // @ts-ignore
97  let tid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.tid);
98  // @ts-ignore
99  let pid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.pid);
100  res.forEach((it, i) => {
101    id[i] = it.id;
102    startNS[i] = it.startNS;
103    dur[i] = it.dur;
104    tid[i] = it.tid;
105    pid[i] = it.pid;
106  });
107
108  let arg1 = {
109    // @ts-ignore
110    id: data.id,
111    // @ts-ignore
112    action: data.action,
113    results: {
114      id: id.buffer,
115      startNS: startNS.buffer,
116      dur: dur.buffer,
117      tid: tid.buffer,
118      pid: pid.buffer,
119    },
120    len: res.length,
121    transfer: transfer,
122  };
123  let arg2 = [
124    id.buffer,
125    startNS.buffer,
126    dur.buffer,
127    tid.buffer,
128    pid.buffer,
129  ];
130  (self as unknown as Worker).postMessage(
131    arg1, arg2,
132  );
133}