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