• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2023 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 { BaseElement, element } from '../../../../../base-ui/BaseElement';
16import { type LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table';
17import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection';
18import '../../../StackBar';
19import { queryBinderByThreadId } from '../../../../database/sql/ProcessThread.sql';
20import { Utils } from '../../base/Utils';
21import { resizeObserver } from '../SheetUtils';
22import { type BinderGroup, type BinderItem } from '../../../../bean/BinderProcessThread';
23import { SliceGroup } from '../../../../bean/StateProcessThread';
24
25@element('tabpane-binders')
26export class TabPaneBinders extends BaseElement {
27  private threadBindersTbl: LitTable | null | undefined;
28  private threadBindersTblSource: Array<SelectionData> = [];
29  private currentSelectionParam: SelectionParam | undefined;
30
31  set data(threadStatesParam: SelectionParam | any) {
32    if (this.currentSelectionParam === threadStatesParam) {
33      return;
34    }
35    this.currentSelectionParam = threadStatesParam;
36    this.initBinderData(threadStatesParam);
37  }
38
39  initBinderData(threadStatesParam: SelectionParam): void {
40    this.threadBindersTbl!.loading = true;
41    this.threadBindersTbl!.recycleDataSource = [];
42    let binderList: BinderItem[] = [];
43    let threadIds = threadStatesParam.threadIds;
44    let processIds: number[] = [...new Set(threadStatesParam.processIds)];
45    queryBinderByThreadId(processIds, threadIds, threadStatesParam.leftNs, threadStatesParam.rightNs).then((result) => {
46      if (result !== null && result.length > 0) {
47        binderList = result;
48      }
49      if (binderList.length > 0) {
50        this.threadBindersTbl!.recycleDataSource = this.transferToTreeData(binderList); // @ts-ignore
51        this.threadBindersTblSource = this.threadBindersTbl!.recycleDataSource;
52        this.threadBindersTbl!.loading = false; // @ts-ignore
53        this.tHeadClick(this.threadBindersTbl!.recycleDataSource);
54      } else if (binderList.length === 0) {
55        this.threadBindersTbl!.recycleDataSource = [];
56        this.threadBindersTblSource = [];
57        this.threadBindersTbl!.loading = false; // @ts-ignore
58        this.tHeadClick(this.threadBindersTbl!.recycleDataSource);
59      }
60    });
61  }
62
63  transferToTreeData(binderList: BinderItem[]): BinderGroup[] {
64    let group: any = {};
65    binderList.forEach((it: BinderItem) => {
66      if (group[`${it.pid}`]) {
67        let process = group[`${it.pid}`];
68        process.totalCount += 1;
69        let thread = process.children.find((child: BinderGroup) => child.title === `T-${it.tid}`);
70        if (thread) {
71          thread.totalCount += 1;
72          thread.binderTransactionCount += it.name === 'binder transaction' ? 1 : 0;
73          thread.binderAsyncRcvCount += it.name === 'binder async rcv' ? 1 : 0;
74          thread.binderReplyCount += it.name === 'binder reply' ? 1 : 0;
75          thread.binderTransactionAsyncCount += it.name === 'binder transaction async' ? 1 : 0;
76        } else {
77          process.children.push({
78            title: `T-${it.tid}`,
79            totalCount: 1,
80            binderTransactionCount: it.name === 'binder transaction' ? 1 : 0,
81            binderAsyncRcvCount: it.name === 'binder async rcv' ? 1 : 0,
82            binderReplyCount: it.name === 'binder reply' ? 1 : 0,
83            binderTransactionAsyncCount: it.name === 'binder transaction async' ? 1 : 0,
84            tid: it.tid,
85            pid: it.pid,
86          });
87        }
88      } else {
89        group[`${it.pid}`] = {
90          title: `P-${it.pid}`,
91          totalCount: 1,
92          tid: it.tid,
93          pid: it.pid,
94          children: [
95            {
96              title: `T-${it.tid}`,
97              totalCount: 1,
98              binderTransactionCount: it.name === 'binder transaction' ? 1 : 0,
99              binderAsyncRcvCount: it.name === 'binder async rcv' ? 1 : 0,
100              binderReplyCount: it.name === 'binder reply' ? 1 : 0,
101              binderTransactionAsyncCount: it.name === 'binder transaction async' ? 1 : 0,
102              tid: it.tid,
103              pid: it.pid,
104            },
105          ],
106        };
107      }
108    });
109    return Object.values(group);
110  }
111
112  private tHeadClick(data: Array<SliceGroup>): void {
113    let labels = this.threadBindersTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label');
114    if (labels) {
115      for (let i = 0; i < labels.length; i++) {
116        let label = labels[i].innerHTML;
117        labels[i].addEventListener('click', () => {
118          if (label.includes('Process') && i === 0) {
119            this.threadBindersTbl!.setStatus(data, false);
120            this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(
121              data,
122              RedrawTreeForm.Retract
123            );
124          } else if (label.includes('Thread') && i === 1) {
125            for (let item of data) {
126              item.status = true;
127              if (item.children !== undefined && item.children.length > 0) {
128                this.threadBindersTbl!.setStatus(item.children, false);
129              }
130            }
131            this.threadBindersTbl!.recycleDs = this.threadBindersTbl!.meauseTreeRowElement(
132              data,
133              RedrawTreeForm.Retract
134            );
135          }
136        });
137      }
138    }
139  }
140
141  initElements(): void {
142    this.threadBindersTbl = this.shadowRoot?.querySelector<LitTable>('#tb-binder-count');
143    this.threadBindersTbl!.itemTextHandleMap.set('title', (value) =>
144      Utils.transferBinderTitle(value, this.currentSelectionParam?.traceId));
145  }
146
147  connectedCallback(): void {
148    super.connectedCallback();
149    resizeObserver(this.parentElement!, this.threadBindersTbl!);
150  }
151
152  initHtml(): string {
153    return `
154      <style>
155      :host{
156          padding: 10px 10px;
157          display: flex;
158          flex-direction: column;
159      }
160      #tb-binder-count{
161          height: auto;
162          overflow-x: auto;
163          width: calc(100vw - 270px)
164      }
165      </style>
166      <lit-table id="tb-binder-count" tree>
167          <lit-table-column title="Process/Thread" data-index="title" key="title"  align="flex-start" width="27%" retract>
168          </lit-table-column>
169          <lit-table-column title="Total count" data-index="totalCount" key="totalCount" align="flex-start">
170          </lit-table-column>
171          <lit-table-column title="Binder transaction count" data-index="binderTransactionCount" key="binderTransactionCount" align="flex-start">
172          </lit-table-column>
173          <lit-table-column title="Binder transaction async count" data-index="binderTransactionAsyncCount" key="binderTransactionAsyncCount" align="flex-start">
174          </lit-table-column>
175          <lit-table-column title="Binder reply count" data-index="binderReplyCount" key="binderReplyCount" align="flex-start">
176          </lit-table-column>
177          <lit-table-column title="Binder async rcv count" data-index="binderAsyncRcvCount" key="binderAsyncRcvCount" align="flex-start">
178          </lit-table-column>
179      </lit-table>
180  `;
181  }
182}
183