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 { Args } from '../CommonArgs';
15import { threadStateList } from '../utils/AllMemoryCache';
16import { filterDataByGroup } from '../utils/DataFilter';
17import { TraficEnum, threadStateToNumber } from '../utils/QueryEnum';
18
19export const chartThreadDataSql = (args: Args):unknown => {
20  return `select B.cpu, max(B.dur) AS dur, B.itid AS id, B.tid AS tid, B.state, B.pid, 
21                 B.ts - ${args.recordStartNS} AS startTime, ifnull(B.arg_setid, -1) AS argSetId, 
22                 ((B.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px
23            from thread_state AS B
24            where B.tid = ${args.tid}
25              and B.pid = ${args.pid}
26              and B.state != 'Running'
27              and startTime + dur >= ${Math.floor(args.startNS)}
28              and startTime <= ${Math.floor(args.endNS)}
29            group by px
30            union all
31    select B.cpu, max(B.dur) AS dur, B.itid AS id, B.tid AS tid, B.state, 
32           B.pid, B.ts - ${args.recordStartNS} AS startTime, ifnull(B.arg_setid, -1) AS argSetId, 
33           ((B.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px
34    from thread_state AS B
35    where B.tid = ${args.tid}
36      and B.pid = ${args.pid}
37      and B.state = 'Running'
38      and startTime + dur >= ${Math.floor(args.startNS)}
39      and startTime <= ${Math.floor(args.endNS)}
40    group by px;
41    ;`;
42};
43
44export const sqlMem = (args: Args): string => {
45  return `select B.cpu, B.dur AS dur, B.itid AS id, B.tid AS tid, B.state, B.pid, B.ts - ${args.recordStartNS} AS startTime, 
46                 ifnull(B.arg_setid, -1) AS argSetId
47            from thread_state AS B
48            where B.tid = ${args.tid}
49            and B.pid = ${args.pid};`;
50};
51
52export function threadDataReceiver(data: unknown, proc: Function): void {
53  //@ts-ignore
54  if (data.params.trafic === TraficEnum.Memory) {
55    //@ts-ignore
56    let key = `${data.params.pid}-${data.params.tid}`;
57    if (!threadStateList.has(key)) {
58      //@ts-ignore
59      threadStateList.set(key, proc(sqlMem(data.params)));
60    }
61    let array = threadStateList.get(key) || [];
62    let res = filterDataByGroup(
63      array,
64      'startTime',
65      'dur', //@ts-ignore
66      data.params.startNS, //@ts-ignore
67      data.params.endNS, //@ts-ignore
68      data.params.width,
69      undefined,
70      //@ts-ignore
71      (a) => a.state === 'Running',
72      false
73    );
74    arrayBufferHandler(data, res, true, array.length === 0);
75    return;
76  } else {
77    //@ts-ignore
78    let sql = chartThreadDataSql(data.params);
79    let res = proc(sql); //@ts-ignore
80    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer, false);
81  }
82}
83
84function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean, isEmpty: boolean): void {
85  //@ts-ignore
86  let startTime = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTime); //@ts-ignore
87  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur); //@ts-ignore
88  let cpu = new Int8Array(transfer ? res.length : data.params.sharedArrayBuffers.cpu); //@ts-ignore
89  let id = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); //@ts-ignore
90  let tid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.tid); //@ts-ignore
91  let state = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.state); //@ts-ignore
92  let pid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.pid); //@ts-ignore
93  let argSetID = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.argSetID);
94  res.forEach((it, i) => {
95    //@ts-ignore
96    data.params.trafic === TraficEnum.ProtoBuffer && (it = it.processThreadData); //@ts-ignore
97    startTime[i] = it.startTime; //@ts-ignore
98    dur[i] = it.dur; //@ts-ignore
99    cpu[i] = it.cpu; //@ts-ignore
100    id[i] = it.id; //@ts-ignore
101    tid[i] = it.tid; //@ts-ignore
102    state[i] = threadStateToNumber(it.state); //@ts-ignore
103    pid[i] = it.pid; //@ts-ignore
104    argSetID[i] = it.argSetId;
105  });
106  (self as unknown as Worker).postMessage(
107    {
108      //@ts-ignore
109      id: data.id, //@ts-ignore
110      action: data.action,
111      results: transfer
112        ? {
113            id: id.buffer,
114            tid: tid.buffer,
115            state: state.buffer,
116            startTime: startTime.buffer,
117            dur: dur.buffer,
118            cpu: cpu.buffer,
119            pid: pid.buffer,
120            argSetID: argSetID.buffer,
121          }
122        : {},
123      len: res.length,
124      transfer: transfer,
125      isEmpty: isEmpty,
126    },
127    transfer
128      ? [startTime.buffer, dur.buffer, cpu.buffer, id.buffer, tid.buffer, state.buffer, pid.buffer, argSetID.buffer]
129      : []
130  );
131}
132