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 { filterDataByGroup } from './utils/DataFilter';
16import { lrqList } from './utils/AllMemoryCache';
17import { Args } from './CommonArgs';
18
19export const chartIrqDataSql = (args: Args): string => {
20  if (args.name === 'irq') {
21    return `
22        select i.ts - ${args.recordStartNS
23      }                                                                                                   as startNs,
24               max(i.dur)                                                                                       as dur,
25               i.depth,
26               ifnull(argsetid, -1)                                                                         as argSetId,
27               i.id,
28               ((i.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) as px
29        from irq i
30        where i.callid = ${args.cpu}
31          and ((i.cat = 'irq' and i.flag = '1') or i.cat = 'ipi')
32          and startNs + dur >= ${Math.floor(args.startNS)}
33          and startNs <= ${Math.floor(args.endNS)}
34        group by px;
35    `;
36  } else {
37    return `
38        select i.ts - ${args.recordStartNS}                                                                 as startNs,
39               max(i.dur)                                                                                       as dur,
40               i.depth,
41               ifnull(argsetid,-1)                                                                            as argSetId,
42               i.id,
43               ((i.ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) as px
44        from irq i
45        where i.callid = ${args.cpu}
46          and i.cat = 'softirq'
47          and startNs + dur >= ${Math.floor(args.startNS)}
48          and startNs <= ${Math.floor(args.endNS)}
49        group by px;
50    `;
51  }
52};
53
54export const chartIrqDataSqlMem = (args: Args): string => {
55  if (args.name === 'irq') {
56    return `
57        select i.ts - t.start_ts as startNs,i.dur,
58        case when i.cat = 'ipi' then 'IPI' || i.name else i.name end as name,
59        i.depth,
60        ifnull(argsetid, -1) as argSetId,
61        i.id 
62        from irq i,trace_range t 
63        where i.callid = ${args.cpu} and ((i.cat = 'irq' and i.flag ='1') or i.cat = 'ipi') 
64    `;
65  } else {
66    return `
67        select i.ts - t.start_ts as startNs,i.dur,i.name,i.depth,ifnull(argsetid, -1) as argSetId,i.id from irq i,
68trace_range t where i.callid = ${args.cpu} and i.cat = 'softirq'
69    `;
70  }
71};
72
73export function irqDataReceiver(data: unknown, proc: Function): void {
74  // @ts-ignore
75  if (data.params.trafic === TraficEnum.Memory) {
76    let res: unknown[];
77    let list: unknown[];
78    // @ts-ignore
79    if (!lrqList.has(data.params.cpu + data.params.name)) {
80      // @ts-ignore
81      list = proc(chartIrqDataSqlMem(data.params));
82      // @ts-ignore
83      lrqList.set(data.params.cpu + data.params.name, list);
84    } else {
85      // @ts-ignore
86      list = lrqList.get(data.params.cpu + data.params.name) || [];
87    }
88    // @ts-ignore
89    res = filterDataByGroup(list || [], 'startNs', 'dur', data.params.startNS, data.params.endNS, data.params.width);
90    arrayBufferHandler(data, res, true);
91  } else {
92    // @ts-ignore
93    let sql = chartIrqDataSql(data.params);
94    let res = proc(sql);
95    // @ts-ignore
96    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer);
97  }
98}
99
100function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean): void {
101  // @ts-ignore
102  let startNS = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNS);
103  // @ts-ignore
104  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur);
105  // @ts-ignore
106  let depth = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.depth);
107  // @ts-ignore
108  let argSetId = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.argSetId);
109  // @ts-ignore
110  let id = new Uint32Array(transfer ? res.length : data.params.sharedArrayBuffers.id);
111  res.forEach((it, i) => {
112    // @ts-ignore
113    data.params.trafic === TraficEnum.ProtoBuffer && (it = it.irqData);
114    // @ts-ignore
115    startNS[i] = it.startNs;
116    // @ts-ignore
117    dur[i] = it.dur;
118    // @ts-ignore
119    depth[i] = it.depth;
120    // @ts-ignore
121    argSetId[i] = it.argSetId;
122    // @ts-ignore
123    id[i] = it.id;
124  });
125  (self as unknown as Worker).postMessage(
126    {
127      // @ts-ignore
128      id: data.id,
129      // @ts-ignore
130      action: data.action,
131      results: transfer
132        ? {
133          startNS: startNS.buffer,
134          dur: dur.buffer,
135          depth: depth.buffer,
136          argSetId: argSetId.buffer,
137          id: id.buffer,
138        }
139        : {},
140      len: res.length,
141      transfer: transfer,
142    },
143    transfer ? [startNS.buffer, dur.buffer, depth.buffer, argSetId.buffer, id.buffer] : []
144  );
145}
146