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 { FuncStruct } from '../ui-worker/ProcedureWorkerFunc';
17import { SearchFuncBean } from '../../bean/SearchFuncBean';
18import { SelectionData } from '../../bean/BoxSelection';
19import { HeapTraceFunctionInfo } from '../../../js-heap/model/DatabaseStruct';
20import { FunctionItem } from '../../bean/BinderProcessThread';
21import { StateGroup } from '../../bean/StateModle';
22import { FuncNameCycle } from '../../bean/BinderProcessThread';
23import { Utils } from '../../component/trace/base/Utils';
24
25export const queryFuncNameCycle = (
26  funcName: string,
27  tIds: string,
28  leftNS: number,
29  rightNS: number
30): Promise<Array<FunctionItem>> =>
31  query(
32    'queryFuncNameCycle',
33    `
34        SELECT  
35              c.ts - r.start_ts AS cycleStartTime, 
36              c.dur,
37              c.id,
38              t.tid,
39              p.pid
40            FROM 
41                callstack c, trace_range r 
42            LEFT JOIN 
43                thread t 
44            ON 
45                c.callid = t.id 
46            LEFT JOIN
47                process p 
48            ON
49                t.ipid = p.id  
50            WHERE 
51                c.name like '${funcName}%' 
52            AND 
53                t.tid = ${tIds} 
54            AND NOT 
55                ((cycleStartTime < ${leftNS}) 
56            OR 
57                ((c.ts - r.start_ts + c.dur) > ${rightNS}))
58          `,
59    {
60      $funcName: funcName,
61      $tIds: tIds,
62      $leftNS: leftNS,
63      $rightNS: rightNS,
64    },
65    { traceId: Utils.currentSelectTrace }
66  );
67
68export const querySingleFuncNameCycle = (
69  funcName: string,
70  tIds: string,
71  leftNS: number,
72  rightNS: number
73): Promise<Array<FunctionItem>> =>
74  query(
75    'querySingleFuncNameCycle',
76    `
77      SELECT 
78            c.name AS funcName, 
79            c.ts - r.start_ts AS cycleStartTime, 
80            c.dur AS cycleDur,
81            c.id,
82            t.tid,
83            p.pid,
84            c.ts - r.start_ts + c.dur AS endTime
85          FROM 
86              callstack c, trace_range r 
87          LEFT JOIN 
88              thread t 
89          ON 
90              c.callid = t.id 
91          LEFT JOIN
92              process p 
93          ON
94              t.ipid = p.id  
95          WHERE 
96              c.name = '${funcName}'
97          AND 
98              t.tid = ${tIds} 
99          AND NOT 
100              ((cycleStartTime < ${leftNS}) 
101          OR 
102              (endTime > ${rightNS}))
103        `,
104    {
105      $funcName: funcName,
106      $tIds: tIds,
107      $leftNS: leftNS,
108      $rightNS: rightNS,
109    }
110  );
111
112export const queryAllFuncNames = async (traceId?: string): Promise<Array<unknown>> => {
113  let list = await query(
114    'queryIsColorIndex',
115    `select
116        colorIndex
117      from
118        callstack
119      limit 1;`,
120    {},
121    { traceId: traceId, action: 'exec-buf' }
122  );
123  let isColorIndex = list.length !== 0 ? true : false;
124  let colorIndexStr = isColorIndex ? ',colorIndex' : '';
125  let allFuncNamesBuffer = await query(
126    'queryAllFuncNames',
127    `select 
128        id,
129        name
130        ${colorIndexStr} 
131      from
132        callstack;`,
133    {},
134    { traceId: traceId, action: 'exec-buf' }
135  );
136  // @ts-ignore
137  return Utils.convertJSON(allFuncNamesBuffer);
138};
139
140export const queryProcessAsyncFunc = (
141  traceRange: {
142    startTs: number;
143    endTs: number;
144  },
145  traceId?: string
146): //@ts-ignore
147  Promise<Array<unknown>> =>
148  query(
149    'queryProcessAsyncFunc',
150    `SELECT
151      A.tid,
152      P.pid,
153      c.ts-${traceRange.startTs} as startTs,
154      c.dur,
155      c.cat,
156      c.id,
157      c.depth,
158      c.argsetid,
159      c.cookie
160    FROM
161      (SELECT id, ts, parent_id, dur, depth, argsetid, cookie, cat from callstack where cookie NOT NULL) c
162    LEFT JOIN thread A ON A.id = c.parent_id
163    LEFT JOIN process P ON P.id = A.ipid
164    WHERE
165      startTs NOT NULL;`,
166    {},
167    { traceId: traceId }
168  );
169
170export const queryProcessAsyncFuncCat = (
171  traceRange: {
172    startTs: number;
173    endTs: number;
174  }
175): Promise<Array<unknown>> =>
176  query(
177    'queryProcessAsyncFuncCat',
178    `
179    select 
180      A.tid,
181      P.pid,   
182      c.cat as threadName,
183      c.name as funName,
184      c.ts-${traceRange.startTs} as startTs,
185      c.dur,
186      c.depth,
187      c.cookie
188    from 
189      (select callid, name, ts, dur, cat, depth, cookie, parent_id from callstack where cookie not null and cat not null and parent_id is null) C
190		left join 
191      thread A on A.id = C.callid
192    left join 
193      process P on P.id = A.ipid      
194    where 
195      startTs not null 
196    order by cat;
197  `,
198    {}
199  );
200
201export const getMaxDepthByTid = (traceId?: string): //@ts-ignore
202  Promise<Array<unknown>> =>
203  query(
204    'getMaxDepthByTid',
205    `SELECT 
206      tid,
207      ipid,
208      maxDepth 
209    FROM
210      thread T
211      LEFT JOIN (
212      SELECT
213        callid,
214        MAX( c.depth + 1 ) AS maxDepth 
215      FROM
216        callstack C 
217      WHERE
218        c.ts IS NOT NULL 
219        AND c.cookie IS NULL 
220      GROUP BY
221        callid 
222      ) C ON T.id = C.callid 
223    WHERE
224      maxDepth NOT NULL`,
225    {},
226    { traceId: traceId }
227  );
228
229export const querySearchFuncData = (
230  funcName: string,
231  tIds: number,
232  leftNS: number,
233  rightNS: number
234): Promise<Array<SearchFuncBean>> =>
235  query(
236    'querySearchFuncData',
237    `select 
238      c.ts - r.start_ts as startTime,
239      c.dur
240    from 
241      callstack c 
242    left join 
243      thread t 
244    on 
245      c.callid = t.id 
246    left join 
247      process p 
248    on 
249      t.ipid = p.id
250    left join 
251      trace_range r
252    where 
253      c.name like '${funcName}%' 
254    and 
255      t.tid = ${tIds} 
256    and
257      not ((startTime < ${leftNS}) or (startTime > ${rightNS}));
258      `
259  );
260
261export const queryFuncRowData = (funcName: string, tIds: number): Promise<Array<SearchFuncBean>> =>
262  query(
263    'queryFuncRowData',
264    `select 
265      c.name as funName,
266      c.ts - r.start_ts as startTime,
267      t.tid as tid
268    from 
269      callstack c 
270    left join 
271      thread t 
272    on 
273      c.callid = t.id 
274    left join 
275      process p 
276    on 
277      t.ipid = p.id
278    left join 
279      trace_range r
280    where 
281      c.name like '${funcName}%' 
282    and 
283      t.tid = ${tIds} 
284              `,
285    { $search: funcName }
286  );
287
288export const fuzzyQueryFuncRowData = (funcName: string, tIds: number):
289  Promise<Array<SearchFuncBean>> =>
290  query(
291    'fuzzyQueryFuncRowData',
292    `select 
293        c.name as funName,
294        c.ts - r.start_ts as startTime,
295        c.ts - r.start_ts + c.dur as endTime,
296        t.tid as tid
297      from 
298        callstack c 
299      left join 
300        thread t 
301      on 
302        c.callid = t.id 
303      left join 
304        process p 
305      on 
306        t.ipid = p.id
307      left join 
308        trace_range r
309      where 
310        c.name like '%${funcName}%' 
311      and 
312        t.tid = ${tIds} 
313              `,
314    { $search: funcName }
315  );
316
317export const getTabSlicesAsyncFunc = (
318  asyncNames: string[],
319  asyncPid: number,
320  asyncTid: number | undefined,
321  leftNS: number,
322  rightNS: number
323): //@ts-ignore
324  Promise<Array<unknown>> => {
325  let condition = `${asyncTid !== null && asyncTid !== undefined ? `and A.tid = ${asyncTid}` : ''}`;
326  let sql = `
327    SELECT 
328      c.name AS name,
329      sum( c.dur ) AS wallDuration,
330      count( c.name ) AS occurrences 
331      FROM
332      (SELECT id, ts, parent_id, dur, name from callstack where cookie NOT NULL) C,
333      trace_range D
334      LEFT JOIN thread A ON A.id = C.parent_id
335      LEFT JOIN process P ON P.id = A.ipid
336    where
337      C.ts > 0
338    and
339      c.dur >= -1
340    and
341      P.pid = ${asyncPid}
342    and
343      c.name in (${asyncNames.map((it) => '\"' + it + '\"').join(',')})
344    and
345      not ((C.ts - D.start_ts + C.dur <  ${leftNS}) or (C.ts - D.start_ts > ${rightNS})) ${condition}
346    group by
347      c.name
348    order by
349    wallDuration desc;`;
350  return query<SelectionData>('getTabSlicesAsyncFunc', sql, {});
351};
352
353export const getTabDetails = (
354  asyncNames: Array<string>,
355  asyncPid: Array<number>,
356  funTids: Array<number>,
357  leftNS: number,
358  rightNS: number
359): //@ts-ignore
360  Promise<Array<unknown>> => {
361  let condition = `
362      and A.tid in (${funTids!.join(',')})
363      and c.cookie is null
364      ${`and P.pid in (${asyncPid.join(',')})`}
365      ${`and c.name in (${asyncNames.map((it) => '\"' + it + '\"').join(',')})`}
366    `;
367  let sql = `
368      SELECT 
369        c.name AS name,
370        c.dur AS duration,
371        P.pid AS processId,
372        P.name AS process,
373        A.tid AS threadId,
374        A.name AS thread,
375        c.ts - D.start_ts as startNs   
376      FROM
377        thread A,trace_range D
378        LEFT JOIN process P ON P.id = A.ipid
379        LEFT JOIN callstack C ON A.id = C.callid
380      where
381          C.ts > 0
382        and
383          c.dur >= -1
384        and
385          not ((C.ts - D.start_ts + C.dur < ${leftNS}) or (C.ts - D.start_ts > ${rightNS})) ${condition}
386    `;
387  return query('getTabDetails', sql, {});
388};
389export const getSfDetails = (
390  asyncNames: Array<string>,
391  asyncPid: number,
392  asyncTid: number | undefined,
393  leftNS: number,
394  rightNS: number
395): //@ts-ignore
396  Promise<Array<unknown>> => {
397  let condition = `
398      and c.parent_id not null
399      ${asyncTid !== null && asyncTid !== undefined ? `and A.tid = ${asyncTid}` : ''}
400      ${`and P.pid = ${asyncPid}`}
401      ${`and c.name in (${asyncNames.map((it) => '\"' + it + '\"').join(',')})`}
402    `;
403  let sql = `
404      SELECT 
405        c.name AS name,
406        c.dur AS duration,
407        P.pid AS processId,
408        P.name AS process,
409        A.tid AS threadId,
410        A.name AS thread,
411        c.ts - D.start_ts as startNs
412        FROM
413        (SELECT id, ts, parent_id, dur, name from callstack where cookie NOT NULL) C,
414        trace_range D
415        LEFT JOIN thread A ON A.id = C.parent_id
416        LEFT JOIN process P ON P.id = A.ipid
417      where
418          C.ts > 0
419        and
420          c.dur >= -1
421        and
422          not ((C.ts - D.start_ts + C.dur < ${leftNS}) or (C.ts - D.start_ts > ${rightNS})) ${condition}
423    `;
424  return query('getSfDetails', sql, {});
425};
426export const getGhDetails = (
427  asyncNames: Array<string>,
428  catName: string,
429  asyncPid: number,
430  leftNS: number,
431  rightNS: number
432): //@ts-ignore
433  Promise<Array<unknown>> => {
434  let sql = `
435        SELECT 
436          c.name AS name,
437          c.dur AS duration,
438          P.pid AS processId,
439          P.name AS process,
440          A.tid AS threadId,
441          A.name AS thread,
442          c.ts - D.start_ts as startNs
443        FROM
444          thread A,trace_range D
445          LEFT JOIN process P ON P.id = A.ipid
446          LEFT JOIN callstack C ON A.id = C.callid
447        where
448            C.ts > 0
449          and
450            c.dur >= -1
451          and 
452            c.cookie not null
453          and 
454            c.cat not null
455          and 
456            c.parent_id is null
457          and 
458            P.pid = ${asyncPid}
459          and
460            cat = '${catName}'
461          and 
462            c.name in (${asyncNames.map((it) => '\"' + it + '\"').join(',')})
463          and
464          not ((C.ts - D.start_ts + C.dur < ${leftNS}) or (C.ts - D.start_ts > ${rightNS}))
465      `;
466  return query('getGhDetails', sql, {});
467};
468export const getTabSlicesAsyncCatFunc = (
469  asyncCatNames: string,
470  asyncCatPid: number,
471  leftNS: number,
472  rightNS: number
473): Promise<Array<unknown>> =>
474  query<SelectionData>(
475    'getTabSlicesAsyncCatFunc',
476    `
477        select
478          c.name as name,
479          sum(c.dur) as wallDuration,
480          count(c.name) as occurrences
481        from
482          thread A, trace_range D
483        left join process P on P.id = A.ipid
484        left join callstack C on A.id = C.callid
485        where
486          C.ts > 0
487        and
488          c.dur >= -1
489        and 
490          c.cookie not null
491        and
492          c.cat not null
493        and 
494          c.parent_id is null
495        and
496          P.pid = ${asyncCatPid}
497        and
498          c.cat = '${asyncCatNames}'
499        and
500          not ((C.ts - D.start_ts + C.dur < ${leftNS}) or (C.ts - D.start_ts > ${rightNS}))
501        group by
502          c.name
503        order by
504          wallDuration desc;`,
505    { $leftNS: leftNS, $rightNS: rightNS }
506  );
507
508export const querySearchFunc = (search: string): Promise<Array<SearchFuncBean>> =>
509  query(
510    'querySearchFunc',
511    `
512   select c.cookie,
513          c.id,
514          c.name as funName,
515          c.ts - r.start_ts as startTime,
516          c.dur,
517          c.depth,
518          t.tid,
519          t.name as threadName,
520          p.pid,
521          c.argsetid,
522          'func' as type 
523   from callstack c left join thread t on c.callid = t.id left join process p on t.ipid = p.id
524   left join trace_range r 
525   where c.name like '%${search}%' and startTime > 0 and cookie IS NULL;
526    `,
527    { $search: search },
528    { traceId: Utils.currentSelectTrace }
529  );
530
531export const querySceneSearchFunc = (search: string, processList: Array<string>):
532  Promise<Array<SearchFuncBean>> =>
533  query(
534    'querySceneSearchFunc',
535    `select c.cookie,
536          c.id,
537          c.name as funName,
538          c.ts - r.start_ts as startTime,
539          c.dur,
540          c.depth,
541          t.tid,
542          t.name as threadName,
543          p.pid,
544          c.argsetid,
545          'func' as type 
546   from callstack c left join thread t on c.callid = t.id left join process p on t.ipid = p.id
547   left join trace_range r
548   where c.name like '%${search}%' ESCAPE '\\' and startTime > 0 and p.pid in (${processList.join(',')}) 
549   and cookie IS NULL;
550    `,
551    { $search: search },
552    { traceId: Utils.currentSelectTrace }
553  );
554
555export const queryHeapFunction = (fileId: number): Promise<Array<HeapTraceFunctionInfo>> =>
556  query(
557    'queryHeapFunction',
558    `SELECT 
559      function_index as index ,
560      function_id as id ,
561      name,
562      script_name as scriptName,
563      script_id as scriptId,
564      line,
565      column
566    FROM js_heap_trace_function_info WHERE file_id = ${fileId}`
567  );
568
569export const queryHeapTraceNode = (
570  fileId: number
571): //@ts-ignore
572  Promise<Array<unknown>> =>
573  query(
574    'queryHeapTraceNode',
575    `SELECT F.name,
576        F.script_name as scriptName,
577        F.script_id as scriptId,
578        F.column,
579        F.line,
580        N.id,
581        N.function_info_index as functionInfoIndex,
582        N.parent_id as parentId,
583        N.count,
584        N.size,
585        IFNULL( S.live_count, 0 ) AS liveCount,
586        IFNULL( S.live_size, 0 ) AS liveSize
587    FROM
588        js_heap_trace_node N
589        LEFT JOIN (
590            SELECT
591                trace_node_id as traceNodeId,
592                SUM( self_size ) AS liveSize,
593                count( * ) AS liveCount
594            FROM
595                js_heap_nodes
596            WHERE
597                file_id = ${fileId}
598                AND trace_node_id != 0
599            GROUP BY
600                trace_node_id
601        ) S ON N.id = S.trace_node_id
602    LEFT JOIN js_heap_trace_function_info F ON (F.file_id = N.file_id
603                AND F.function_index = N.function_info_index)
604    WHERE
605        N.file_id = ${fileId}
606    ORDER BY
607        N.id`
608  );
609
610export const queryTaskPoolOtherRelationData = (ids: Array<number>, tid: number):
611  Promise<Array<FuncStruct>> => {
612  let sqlStr = `select
613                    c.ts-D.start_ts as startTs,
614                    c.dur,
615                    c.name as funName,
616                    c.argsetid,
617                    c.depth,
618                    c.id as id,
619                    A.itid as itid,
620                    A.ipid as ipid
621                from thread A,trace_range D
622                                  left join callstack C on A.id = C.callid
623                where startTs not null and c.cookie is null and tid = $tid and c.id in (${ids.join(',')})`;
624  return query('queryTaskPoolOtherRelationData', sqlStr, { $ids: ids, $tid: tid });
625};
626
627export const queryTaskPoolRelationData = (ids: Array<number>, tids: Array<number>):
628  Promise<Array<FuncStruct>> => {
629  let sqlStr = `select
630        c.ts-D.start_ts as startTs,
631        c.dur,
632        c.name as funName,
633        c.argsetid,
634        c.depth,
635        c.id as id,
636        A.itid as itid,
637        A.ipid as ipid
638    from thread A,trace_range D
639                      left join callstack C on A.id = C.callid
640    where startTs not null and c.cookie is null and c.id in (${ids.join(',')}) and tid in (${tids.join(
641    ','
642  )})`;
643  return query('queryTaskPoolRelationData', sqlStr, { $ids: ids, $tids: tids });
644};
645
646export const queryStatesCut = (tIds: Array<number>, leftNS: number, rightNS: number):
647  Promise<Array<StateGroup>> =>
648  query<StateGroup>(
649    'queryBinderByThreadId',
650    `
651    select
652    B.id,
653    B.pid,
654    B.tid,
655    B.dur,
656    B.cpu,
657    B.state,
658    B.ts - C.start_ts AS ts,
659    B.dur + B.ts as endTs
660  from
661    thread_state AS B,trace_range AS C
662  where
663    B.tid in (${tIds.join(',')})
664  and
665    not ((B.ts + + ifnull(B.dur,0) < ($leftStartNs + C.start_ts)) 
666    or (B.ts + B.dur > ($rightEndNs + C.start_ts)))
667  order by
668    B.pid;
669        `,
670    {
671      $tIds: tIds,
672      $leftStartNs: leftNS,
673      $rightEndNs: rightNS,
674    }
675  );
676
677export const queryLoopFuncNameCycle = (
678  funcName: string,
679  tIds: string,
680  leftNS: number,
681  rightNS: number
682): Promise<Array<FuncNameCycle>> =>
683  query(
684    'queryLoopFuncNameCycle',
685    `
686        SELECT 
687            c.name AS funcName,
688            c.ts - r.start_ts AS cycleStartTime,
689            0 AS cycleDur,
690            c.id,
691            t.tid,
692            p.pid
693          FROM
694              callstack c, trace_range r 
695            LEFT JOIN 
696              thread t 
697            ON 
698              c.callid = t.id 
699            LEFT JOIN  
700              process p 
701            ON 
702              t.ipid = p.id  
703          WHERE 
704              c.name like '${funcName}%'  
705            AND 
706              t.tid = ${tIds}
707            AND NOT 
708              ((cycleStartTime < ${leftNS}) 
709            OR  
710              (cycleStartTime > ${rightNS})) 
711          `,
712    {
713      $funcName: funcName,
714      $tIds: tIds,
715      $leftNS: leftNS,
716      $rightNS: rightNS,
717    }
718  );
719
720export const querySingleFuncNameCycleStates = (
721  funcName: string,
722  tIds: string,
723  leftNS: number,
724  rightNS: number
725): Promise<Array<FuncNameCycle>> =>
726  query(
727    'querySingleFuncNameCycle',
728    `
729          SELECT 
730                c.name AS funcName, 
731                c.ts - r.start_ts AS cycleStartTime, 
732                c.dur AS cycleDur,
733                c.id,
734                t.tid,
735                p.pid,
736                c.ts - r.start_ts + c.dur AS endTime
737              FROM 
738                  callstack c, trace_range r 
739              LEFT JOIN 
740                  thread t 
741              ON 
742                  c.callid = t.id 
743              LEFT JOIN
744                  process p 
745              ON
746                  t.ipid = p.id  
747              WHERE 
748                  c.name like '${funcName}%' 
749              AND 
750                  t.tid = ${tIds} 
751              AND NOT 
752                  ((cycleStartTime < ${leftNS}) 
753              OR 
754                  (endTime > ${rightNS}))
755            `,
756    {
757      $funcName: funcName,
758      $tIds: tIds,
759      $leftNS: leftNS,
760      $rightNS: rightNS,
761    }
762  );
763