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 { cpuFreqLimitList } from '../utils/AllMemoryCache';
17import { Args } from '../CommonArgs';
18
19export const chartCpuFreqLimitDataSql = (args: Args): string => {
20  const endNS = args.endNS;
21  const startNS = args.startNS;
22  const recordStartNS = args.recordStartNS;
23  const cpu = args.cpu;
24  const width = args.width;
25  const maxId = args.maxId;
26  const minId = args.minId;
27  return `
28      SELECT 
29             max AS max,
30             min AS min,
31             value,
32             max(dura)     AS dur,
33             startNs AS startNs,
34             ${cpu} AS cpu,
35          (startNs / (${Math.floor((endNS - startNS) / width)})) AS px
36      FROM (
37          SELECT  ts - ${recordStartNS} AS startNs,
38          case when dur is null then (${endNS + recordStartNS} - ts) else dur end AS dura,
39          value,
40          MAX (value) AS max,
41          MIN (value) AS min
42          FROM measure
43          WHERE filter_id IN (${maxId}, ${minId})
44            AND startNs + dura >= ${Math.floor(startNS)}
45            AND startNs <= ${Math.floor(endNS)}
46          GROUP BY ts
47          ) AS subquery
48      GROUP BY px;
49  `;
50};
51
52export const chartCpuFreqLimitDataSqlMem = (args: Args): string => {
53  return `
54      select ts - ${args.recordStartNS} as startNs,
55           dur,
56           max(value) as max,
57           min(value) as min,
58            $cpu as cpu 
59    from measure where filter_id in (${args.maxId}, ${args.minId}) 
60                 group by ts;
61  `;
62};
63
64export function cpuFreqLimitReceiver(data: unknown, proc: Function): void {
65  // @ts-ignore
66  if (data.params.trafic === TraficEnum.Memory) {
67    let res: unknown[];
68    let list: unknown[];
69    // @ts-ignore
70    if (!cpuFreqLimitList.has(data.params.cpu)) {
71      // @ts-ignore
72      let sql = chartCpuFreqLimitDataSqlMem(data.params);
73      list = proc(sql);
74      for (let i = 0; i < list.length; i++) {
75        if (i < list.length - 1) {
76          // @ts-ignore
77          list[i].dur = list[i + 1].startNs - list[i].startNs;
78        } else {
79          // @ts-ignore
80          list[i].dur = data.params.recordEndNS - data.params.recordStartNS - list[i].startNs;
81        }
82      }
83      // @ts-ignore
84      cpuFreqLimitList.set(data.params.cpu, list);
85    } else {
86      // @ts-ignore
87      list = cpuFreqLimitList.get(data.params.cpu) || [];
88    }
89    res = filterDataByGroup(
90      list || [],
91      'startNs',
92      'dur',
93      // @ts-ignore
94      data.params.startNS,
95      // @ts-ignore
96      data.params.endNS,
97      // @ts-ignore
98      data.params.width,
99      'value'
100    );
101    arrayBufferHandler(data, res, true);
102  } else {
103    // @ts-ignore
104    let sql = chartCpuFreqLimitDataSql(data.params);
105    let res = proc(sql);
106    // @ts-ignore
107    arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer);
108  }
109}
110
111function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean): void {
112  // @ts-ignore
113  let startNs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNs);
114  // @ts-ignore
115  let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur);
116  // @ts-ignore
117  let value = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.value);
118  // @ts-ignore
119  let max = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.max);
120  // @ts-ignore
121  let min = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.min);
122  res.forEach((it, i) => {
123    // @ts-ignore
124    data.params.trafic === TraficEnum.ProtoBuffer && (it = it.cpuFreqLimitData);
125    // @ts-ignore
126    startNs[i] = it.startNs;
127    // @ts-ignore
128    dur[i] = it.dur;
129    // @ts-ignore
130    value[i] = it.value;
131    // @ts-ignore
132    max[i] = it.max;
133    // @ts-ignore
134    min[i] = it.min;
135  });
136  (self as unknown as Worker).postMessage(
137    {
138      // @ts-ignore
139      id: data.id,
140      // @ts-ignore
141      action: data.action,
142      results: transfer
143        ? {
144          startNs: startNs.buffer,
145          dur: dur.buffer,
146          value: value.buffer,
147          max: max.buffer,
148          min: min.buffer,
149        }
150        : {},
151      len: res.length,
152      transfer: transfer,
153    },
154    transfer ? [startNs.buffer, dur.buffer, value.buffer, max.buffer, min.buffer] : []
155  );
156}
157