1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15import { query } from '../SqlLite';
16import { NativeHookMalloc, NativeHookProcess, NativeHookSampleQueryInfo } from '../../bean/NativeHook';
17
18export const queryNativeHookResponseTypes = (
19  leftNs: number,
20  rightNs: number,
21  types: Array<string | number>,
22  pid: number,
23  isStatistic: boolean
24): //@ts-ignore
25  Promise<Array<unknown>> => {
26  const table = isStatistic ? 'native_hook_statistic' : 'native_hook';
27  const tsKey = isStatistic ? 'ts' : 'start_ts';
28  const type = isStatistic ? 'type' : 'event_type';
29  return query(
30    'queryNativeHookResponseTypes',
31    `
32          select 
33            distinct last_lib_id as lastLibId,
34            data_dict.data as value 
35          from 
36            ${table} A ,trace_range B
37            left join data_dict on A.last_lib_id = data_dict.id 
38          where
39          A.${tsKey} - B.start_ts
40          between ${leftNs} and ${rightNs} and A.${type} in (${types.join(',')})
41          and A.ipid = ${pid};
42      `,
43    { $leftNs: leftNs, $rightNs: rightNs, $types: types, $pid: pid }
44  );
45};
46export const queryNativeHookStatistics = (
47  leftNs: number,
48  rightNs: number,
49  ipid: number
50): Promise<Array<NativeHookMalloc>> =>
51  query(
52    'queryNativeHookStatistics',
53    `
54    select
55      event_type as eventType,
56      sub_type_id as subTypeId,
57      max(heap_size) as max,
58      sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte,
59      sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount,
60      sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte,
61      sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount
62    from
63      native_hook A,
64      trace_range B
65    where
66      (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}
67     and (event_type = 'AllocEvent' or event_type = 'MmapEvent')
68     and ipid = ${ipid}
69    group by event_type;`,
70    { $leftNs: leftNs, $rightNs: rightNs }
71  );
72
73export const queryNativeHookStatisticsMalloc = (
74  leftNs: number,
75  rightNs: number,
76  ipid: number
77): Promise<Array<NativeHookMalloc>> =>
78  query(
79    'queryNativeHookStatisticsMalloc',
80    `
81    select
82      event_type as eventType,
83      heap_size as heapSize,
84      sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte,
85      sum(case when ((A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount,
86      sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte,
87      sum(case when ((A.end_ts - B.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount
88    from
89      native_hook A,
90      trace_range B
91    where
92      (A.start_ts - B.start_ts) between ${leftNs} and ${rightNs}
93    and
94      (event_type = 'AllocEvent' or event_type = 'MmapEvent')
95    and 
96      sub_type_id is null
97      and ipid = ${ipid}
98    group by
99      event_type,
100      heap_size
101    order by heap_size desc
102    `,
103    { $leftNs: leftNs, $rightNs: rightNs }
104  );
105
106export const queryNativeHookStatisticsSubType = (
107  leftNs: number,
108  rightNs: number,
109  ipid: number
110): Promise<Array<NativeHookMalloc>> =>
111  query(
112    'queryNativeHookStatisticsSubType',
113    `
114    select
115      event_type as eventType,
116      sub_type_id as subTypeId,
117      max(heap_size) as max,
118      sum(case when ((NH.start_ts - TR.start_ts) between ${leftNs} and ${rightNs}) then heap_size else 0 end) as allocByte,
119      sum(case when ((NH.start_ts - TR.start_ts) between ${leftNs} and ${rightNs}) then 1 else 0 end) as allocCount,
120      sum(case when ((NH.end_ts - TR.start_ts) between ${leftNs} and ${rightNs} ) then heap_size else 0 end) as freeByte,
121      sum(case when ((NH.end_ts - TR.start_ts) between ${leftNs} and ${rightNs} ) then 1 else 0 end) as freeCount
122    from
123      native_hook NH,
124      trace_range TR
125    where
126      (NH.start_ts - TR.start_ts) between ${leftNs} and ${rightNs}
127    and
128      (event_type = 'MmapEvent')
129    and ipid = ${ipid}
130    group by
131      event_type,sub_type_id;
132        `,
133    { $leftNs: leftNs, $rightNs: rightNs }
134  );
135
136export const queryNativeHookSubType = (
137  leftNs: number,
138  rightNs: number,
139  ipid: number
140): //@ts-ignore
141  Promise<Array<unknown>> =>
142  query(
143    'queryNativeHookSubType',
144    `select distinct(
145  case when sub_type_id is null  then -1 else sub_type_id end
146) as subTypeId,
147(case when sub_type_id is null then 'Other MmapEvent' else DD.data end) as subType
148      from
149        native_hook NH,
150        trace_range TR
151      left join data_dict DD on NH.sub_type_id = DD.id
152where event_type = 'MmapEvent' and
153        (NH.start_ts - TR.start_ts) between ${leftNs} and ${rightNs}
154        and ipid = ${ipid}
155        `,
156    { $leftNs: leftNs, $rightNs: rightNs }
157  );
158
159export const queryNativeHookStatisticSubType = (
160  leftNs: number,
161  rightNs: number,
162  ipid: number
163): //@ts-ignore
164  Promise<Array<unknown>> =>
165  query(
166    'queryNativeHookStatisticSubType',
167    `SELECT DISTINCT
168      CASE
169        WHEN type = 3 AND sub_type_id NOT NULL THEN sub_type_id
170        ELSE type
171      END AS subTypeId,
172      CASE
173        WHEN type = 2 THEN 'FILE_PAGE_MSG'
174        WHEN type = 3 AND sub_type_id NOT NULL THEN D.data
175        WHEN type = 3 THEN 'MEMORY_USING_MSG'
176        ELSE 'Other MmapEvent'
177      END AS subType
178      FROM
179        native_hook_statistic NHS
180        LEFT JOIN data_dict D ON NHS.sub_type_id = D.id,
181        trace_range TR
182      WHERE
183        NHS.type >= 1 AND
184        (NHS.ts - TR.start_ts) between ${leftNs} and ${rightNs}
185        AND ipid = ${ipid}
186      `,
187    { $leftNs: leftNs, $rightNs: rightNs }
188  );
189
190export const queryNativeHookStatisticsCount = (): Promise<Array<{ num: number }>> =>
191  query('queryNativeHookStatisticsCount', `select count(1) num from native_hook_statistic`, {});
192
193export const queryNativeHookProcess = (table: string): Promise<Array<NativeHookProcess>> => {
194  let sql = `
195    select
196      distinct ${table}.ipid,
197      pid,
198      name
199    from
200      ${table}
201    left join
202      process p
203    on
204      ${table}.ipid = p.id
205    `;
206  return query('queryNativeHookProcess', sql, {});
207};
208
209export const queryNativeHookSnapshotTypes = (ipid: number): Promise<Array<NativeHookSampleQueryInfo>> =>
210  query(
211    'queryNativeHookSnapshotTypes',
212    `
213select
214      event_type as eventType,
215      data as subType
216    from
217      native_hook left join data_dict on native_hook.sub_type_id = data_dict.id
218    where
219      (event_type = 'AllocEvent' or event_type = 'MmapEvent')
220      and ipid = ${ipid}
221    group by
222      event_type,data;`,
223    {}
224  );
225
226export const queryAllHookData = (rightNs: number, ipid: number): Promise<Array<NativeHookSampleQueryInfo>> =>
227  query(
228    'queryAllHookData',
229    `
230    select
231      callchain_id as eventId,
232      event_type as eventType,
233      data as subType,
234      addr,
235      heap_size as growth,
236      (n.start_ts - t.start_ts) as startTs,
237      (n.end_ts - t.start_ts) as endTs
238    from
239      native_hook n left join data_dict on n.sub_type_id = data_dict.id,
240      trace_range t
241    where
242      (event_type = 'AllocEvent' or event_type = 'MmapEvent')
243      and ipid = ${ipid}
244    and
245      n.start_ts between t.start_ts and ${rightNs} + t.start_ts`,
246    { $rightNs: rightNs }
247  );
248