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 { threadCallStackList } from '../utils/AllMemoryCache';
16import { filterDataByGroupLayer } from '../utils/DataFilter';
17import { TraficEnum } from '../utils/QueryEnum';
18
19export const chartFuncDataSql = (args: Args): string => {
20  return `
21    select
22        startTs,
23        dur,
24        ifnull(argsetid, -1) as argsetid,
25        depth,
26        id,
27        max(dur2) as dur2,
28        (startTs) / (${Math.floor((args.endNS - args.startNS) / args.width)}) + (depth * ${
29    args.width
30  })                           AS px
31    from (
32      select c.ts - ${args.recordStartNS} as startTs,
33             c.dur as dur,
34             case when (c.dur=-1 or c.dur is null ) then ${args.recordEndNS} else c.dur end                   as dur2,
35             c.argsetid,
36             c.depth,
37             c.id                         as id
38             --c.name                       as funName,
39      from callstack C
40      where startTs not null
41        and c.cookie is null
42        and c.callid in (select id from thread where tid=${args.tid}
43        and ipid=${args.ipid})
44        and startTs + dur2 >= ${Math.floor(args.startNS)}
45        and startTs <= ${Math.floor(args.endNS)}
46    )
47    group by px;  
48`;
49};
50
51export const chartFuncDataSqlMem = (args: Args): string => {
52  return `select c.ts - ${args.recordStartNS} as startTs,
53             c.dur                  as dur,
54             ifnull(c.argsetid, -1) as argsetid,
55             c.depth,
56             c.id                         as id
57      from callstack C
58      where startTs not null
59        and c.cookie is null
60        and c.callid in (select id from thread where tid=${args.tid}
61        and ipid=${args.ipid})`;
62};
63export function funcDataReceiver(data: unknown, proc: Function): void {
64  //@ts-ignore
65  if (data.params.trafic === TraficEnum.Memory) {
66    //@ts-ignore
67    let key = `${data.params.tid}${data.params.ipid}`;
68    if (!threadCallStackList.has(key)) {
69      //@ts-ignore
70      let list = proc(chartFuncDataSqlMem(data.params));
71      for (let i = 0; i < list.length; i++) {
72        if (list[i].dur === -1 || list[i].dur === null || list[i].dur === undefined) {
73          list[i].nofinish = 1; //@ts-ignore
74          let totalNs = data.params.recordEndNS - data.params.recordStartNS;
75          list[i].dur = totalNs - list[i].startTs;
76        } else {
77          list[i].nofinish = 0;
78        }
79      }
80      threadCallStackList.set(key, list);
81    }
82    //@ts-ignore
83    let array = data.params.expand ? (threadCallStackList.get(key) || []) : arrayFoldHandler(key);
84    let res = filterDataByGroupLayer(
85      //@ts-ignore
86      array,
87      'depth',
88      'startTs',
89      'dur', //@ts-ignore
90      data.params.startNS, //@ts-ignore
91      data.params.endNS, //@ts-ignore
92      data.params.width
93    );
94    //@ts-ignore
95    arrayBufferHandler(data, res, true, array.length === 0);
96  } else {
97    //@ts-ignore
98    let sql = chartFuncDataSql(data.params);
99    let res = proc(sql); //@ts-ignore
100    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer, false);
101  }
102}
103
104//func泳道折叠时,过滤出depth为0的数据
105function arrayFoldHandler(key: unknown): unknown {
106  //@ts-ignore
107  return (threadCallStackList.get(key) || []).filter((it) => it.depth === 0 );
108}
109
110function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean, isEmpty: boolean): void {
111  //@ts-ignore
112  let startTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTs); //@ts-ignore
113  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur); //@ts-ignore
114  let argsetid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.argsetid); //@ts-ignore
115  let depth = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.depth); //@ts-ignore
116  let id = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); //@ts-ignore
117  let nofinish = new Uint8Array(transfer ? res.length : data.params.sharedArrayBuffers.nofinish);
118  res.forEach((it, i) => {
119    //@ts-ignore
120    data.params.trafic === TraficEnum.ProtoBuffer && (it = it.processFuncData); //@ts-ignore
121    startTs[i] = it.startTs; //@ts-ignore
122    dur[i] = it.dur; //@ts-ignore
123    argsetid[i] = it.argsetid; //@ts-ignore
124    depth[i] = it.depth; //@ts-ignore
125    id[i] = it.id; //@ts-ignore
126    nofinish[i] = it.nofinish;
127  });
128  (self as unknown as Worker).postMessage(
129    {
130      //@ts-ignore
131      id: data.id, //@ts-ignore
132      action: data.action,
133      results: transfer
134        ? {
135            startTs: startTs.buffer,
136            dur: dur.buffer,
137            argsetid: argsetid.buffer,
138            depth: depth.buffer,
139            id: id.buffer,
140            nofinish: nofinish.buffer,
141          }
142        : {},
143      len: res.length,
144      transfer: transfer,
145      isEmpty: isEmpty,
146    },
147    transfer ? [startTs.buffer, dur.buffer, argsetid.buffer, depth.buffer, id.buffer, nofinish.buffer] : []
148  );
149}
150