• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
15
16import { BaseElement, element } from '../../../../../base-ui/BaseElement';
17import { LitTable } from '../../../../../base-ui/table/lit-table';
18import { SelectionParam } from '../../../../bean/BoxSelection';
19import '../../../../../base-ui/slicer/lit-slicer';
20import { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar';
21import { procedurePool } from '../../../../database/Procedure';
22import {
23  FileSysEvent,
24  IoCompletionTimes,
25  VM_TYPE_MAP,
26} from '../../../../database/logic-worker/ProcedureLogicWorkerFileSystem';
27import { FilterData, TabPaneFilter } from '../TabPaneFilter';
28import { getTabIoCompletionTimesType } from '../../../../database/sql/SqlLite.sql';
29import { TabPaneIoCompletionTimesHtml } from './TabPaneIoCompletionTimes.html';
30
31@element('tabpane-io-completiontimes')
32export class TabPaneIoCompletionTimes extends BaseElement {
33  // @ts-ignore
34  private defaultNativeTypes = ['All', ...Object.values(VM_TYPE_MAP)];
35  private native_type: Array<string> = [...this.defaultNativeTypes];
36  private ioCompletionTimesTbl: LitTable | null | undefined;
37  private ioCompletionTimesTblData: LitTable | null | undefined;
38  private ioCompletionTimesProgressEL: LitProgressBar | null | undefined;
39  private ioCompletionTimesLoadingList: number[] = [];
40  private ioCompletionTimesLoadingPage: unknown;
41  private currentSelection: SelectionParam | undefined | null;
42  private ioCompletionTimesSource: Array<IoCompletionTimes> = [];
43  private ioCompletionTimesQueryDataSource: Array<IoCompletionTimes> = [];
44  private ioCompletionTimesSelection: Array<unknown> = [];
45
46  set data(ioCompletionTimesSelection: SelectionParam | null | undefined) {
47    if (ioCompletionTimesSelection === this.currentSelection) {
48      return;
49    }
50    this.currentSelection = ioCompletionTimesSelection;
51    this.initFilterTypes(ioCompletionTimesSelection!).then((): void => {
52      this.queryData(ioCompletionTimesSelection!);
53    });
54    if (this.ioCompletionTimesTbl) {
55      // @ts-ignore
56      this.ioCompletionTimesTbl.shadowRoot.querySelector('.table').style.height = `${
57        this.parentElement!.clientHeight - 20 - 31
58      }px`;
59      this.ioCompletionTimesTbl.recycleDataSource = [];
60    }
61    if (this.ioCompletionTimesTblData) {
62      // @ts-ignore
63      this.ioCompletionTimesTblData.shadowRoot.querySelector('.table').style.height = `${
64        this.parentElement!.clientHeight - 20 - 31
65      }px`;
66      this.ioCompletionTimesTblData.recycleDataSource = [];
67    }
68  }
69
70  connectedCallback(): void {
71    new ResizeObserver((): void => {
72      if (this.parentElement?.clientHeight !== 0) {
73        if (this.ioCompletionTimesTbl) {
74          // @ts-ignore
75          this.ioCompletionTimesTbl.shadowRoot.querySelector('.table').style.height = `${
76            this.parentElement!.clientHeight - 10 - 33
77          }px`;
78          this.ioCompletionTimesTbl.reMeauseHeight();
79        }
80        if (this.ioCompletionTimesTblData) {
81          // @ts-ignore
82          this.ioCompletionTimesTblData.shadowRoot.querySelector('.table').style.height = `${
83            this.parentElement!.clientHeight - 10 - 33
84          }px`;
85          this.ioCompletionTimesTblData.reMeauseHeight();
86        } // @ts-ignore
87        this.ioCompletionTimesLoadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`;
88      }
89    }).observe(this.parentElement!);
90  }
91
92  initElements(): void {
93    this.ioCompletionTimesLoadingPage = this.shadowRoot?.querySelector('.io-completiontimes-loading');
94    this.ioCompletionTimesProgressEL = this.shadowRoot?.querySelector('.io-completion-progress') as LitProgressBar;
95    this.ioCompletionTimesTbl = this.shadowRoot?.querySelector<LitTable>('#tbl-io-completion-times');
96    this.ioCompletionTimesTblData = this.shadowRoot?.querySelector<LitTable>('#tbr-io-completion-times');
97    this.ioCompletionTimesTbl!.addEventListener('row-click', (e) => {
98      // @ts-ignore
99      let ioCompletionTimeData = e.detail.data as FileSysEvent;
100      procedurePool.submitWithName(
101        'logic0',
102        'fileSystem-queryStack',
103        { callchainId: ioCompletionTimeData.callchainId },
104        undefined,
105        (res: unknown) => {
106          // @ts-ignore
107          this.ioCompletionTimesTblData!.recycleDataSource = res;
108        }
109      );
110    });
111    this.ioCompletionTimesTbl!.addEventListener('column-click', (evt: Event): void => {
112      // @ts-ignore
113      this.ioCompletionTimesSortKey = evt.detail.key;
114      // @ts-ignore
115      this.ioCompletionTimesSortType = evt.detail.sort;
116      // @ts-ignore
117      this.sortioCompletionTimesTable(evt.detail.key, evt.detail.sort);
118    });
119    this.shadowRoot?.querySelector<TabPaneFilter>('#io-completion-filter')!.getFilterData((data: FilterData): void => {
120      let index = parseInt(data.firstSelect || '0');
121      if (index > this.defaultNativeTypes.length - 1) {
122        this.filterTypeData(this.ioCompletionTimesSelection[index - this.defaultNativeTypes.length]);
123      } else {
124        this.filterTypeData(undefined);
125      }
126      this.ioCompletionTimesTbl!.recycleDataSource = this.ioCompletionTimesSource;
127    });
128  }
129
130  async initFilterTypes(ioCompletionTimeParam: SelectionParam): Promise<void> {
131    let filter = this.shadowRoot?.querySelector<TabPaneFilter>('#io-completion-filter');
132    let typeKeys = await getTabIoCompletionTimesType(ioCompletionTimeParam.leftNs, ioCompletionTimeParam.rightNs);
133    this.defaultNativeTypes = ['All'];
134    this.ioCompletionTimesSelection = [];
135    typeKeys.forEach((item: string): void => {
136      // @ts-ignore
137      this.defaultNativeTypes.push(`${item.tier}`);
138    });
139    this.native_type = [...this.defaultNativeTypes];
140    filter!.setSelectList([...this.defaultNativeTypes], null, 'Tier');
141    filter!.firstSelect = '0';
142  }
143
144  async fromStastics(ioCompletionTimeParam: SelectionParam | unknown): Promise<void> {
145    // @ts-ignore
146    if (ioCompletionTimeParam.fileSystemIoData === undefined) {
147      return;
148    }
149    this.ioCompletionTimesTblData!.recycleDataSource = [];
150    this.ioCompletionTimesTblData?.clearAllSelection(undefined);
151    let filter = this.shadowRoot?.querySelector<TabPaneFilter>('#io-completion-filter');
152    if (this.currentSelection !== ioCompletionTimeParam) {
153      // @ts-ignore
154      await this.initFilterTypes(ioCompletionTimeParam);
155    } // @ts-ignore
156    let typeIndexOf = this.native_type.indexOf(ioCompletionTimeParam.fileSystemIoData.path.value);
157    if (typeIndexOf === -1) {
158      // @ts-ignore
159      this.ioCompletionTimesSelection.push(ioCompletionTimeParam.fileSystemIoData.path); // @ts-ignore
160      this.native_type.push(ioCompletionTimeParam.fileSystemIoData.path.value);
161      typeIndexOf = this.native_type.length - 1;
162    }
163    if (this.currentSelection !== ioCompletionTimeParam) {
164      // @ts-ignore
165      this.currentSelection = ioCompletionTimeParam;
166      filter!.setSelectList(this.native_type, null, 'Tier');
167      filter!.firstSelect = `${typeIndexOf}`; // @ts-ignore
168      this.queryData(ioCompletionTimeParam);
169    } else {
170      if (typeIndexOf === parseInt(filter!.firstSelect)) {
171        return;
172      }
173      filter!.setSelectList(this.native_type, null, 'Tier');
174      filter!.firstSelect = `${typeIndexOf}`; // @ts-ignore
175      this.filterTypeData(ioCompletionTimeParam?.fileSystemIoData?.path || undefined); // @ts-ignore
176      ioCompletionTimeParam.fileSystemIoData = undefined;
177      this.ioCompletionTimesTbl!.recycleDataSource = this.ioCompletionTimesSource;
178    }
179  }
180
181  queryData(ioCompletionTimeParam: SelectionParam): void {
182    this.ioCompletionTimesLoadingList.push(1);
183    this.ioCompletionTimesProgressEL!.loading = true; // @ts-ignore
184    this.ioCompletionTimesLoadingPage.style.visibility = 'visible';
185    this.ioCompletionTimesSource = [];
186    this.ioCompletionTimesQueryDataSource = [];
187    procedurePool.submitWithName(
188      'logic0',
189      'fileSystem-queryIOEvents',
190      {
191        leftNs: ioCompletionTimeParam.leftNs,
192        rightNs: ioCompletionTimeParam.rightNs,
193        diskIOipids: ioCompletionTimeParam.diskIOipids,
194      },
195      undefined,
196      (res: unknown): void => {
197        // @ts-ignore
198        this.ioCompletionTimesSource = this.ioCompletionTimesSource.concat(res.data); // @ts-ignore
199        this.ioCompletionTimesQueryDataSource = this.ioCompletionTimesQueryDataSource.concat(res.data);
200        // @ts-ignore
201        this.filterTypeData(ioCompletionTimeParam?.fileSystemIoData?.path || undefined);
202        ioCompletionTimeParam.fileSystemIoData = undefined; // @ts-ignore
203        res.data = null; // @ts-ignore
204        if (!res.isSending) {
205          this.ioCompletionTimesTbl!.recycleDataSource = this.ioCompletionTimesSource;
206          this.ioCompletionTimesLoadingList.splice(0, 1);
207          if (this.ioCompletionTimesLoadingList.length === 0) {
208            this.ioCompletionTimesProgressEL!.loading = false; // @ts-ignore
209            this.ioCompletionTimesLoadingPage.style.visibility = 'hidden';
210          }
211        }
212      }
213    );
214  }
215
216  filterTypeData(pathTypeData: unknown): void {
217    let filter = this.shadowRoot?.querySelector<TabPaneFilter>('#io-completion-filter');
218    let firstSelect = filter!.firstSelect;
219    let tier = -1;
220    let path = '';
221    let pid = -1;
222    if (parseInt(firstSelect) <= this.defaultNativeTypes.length - 1) {
223      let index = parseInt(firstSelect);
224      tier = index === 0 ? -1 : parseInt(this.defaultNativeTypes[index]);
225    } else if (pathTypeData !== undefined) {
226      // @ts-ignore
227      tier = parseInt(pathTypeData.tier); // @ts-ignore
228      path = pathTypeData.path || ''; // @ts-ignore
229      pid = pathTypeData.pid || -1;
230    } else {
231      return;
232    }
233    let isTierFilter = false;
234    let isPidFilter = false;
235    let isPathFilter = false;
236    this.ioCompletionTimesSource = this.ioCompletionTimesQueryDataSource.filter((ioCompletionTimesQueryData) => {
237      if (tier === -1) {
238        isTierFilter = true;
239      } else {
240        isTierFilter = ioCompletionTimesQueryData.tier === tier;
241      }
242      if (pid === -1) {
243        isPidFilter = true;
244      } else {
245        isPidFilter = ioCompletionTimesQueryData.pid === pid;
246      }
247      isPathFilter = path === '' || ioCompletionTimesQueryData.path === path;
248      return isTierFilter && isPidFilter && isPathFilter;
249    });
250  }
251
252  sortioCompletionTimesTable(ioCompletionTimesKey: string, type: number): void {
253    if (type === 0) {
254      this.ioCompletionTimesTbl!.recycleDataSource = this.ioCompletionTimesSource;
255    } else {
256      let arr = Array.from(this.ioCompletionTimesSource);
257      this.sortHandle(arr, ioCompletionTimesKey, type);
258      this.ioCompletionTimesTbl!.recycleDataSource = arr;
259    }
260  }
261
262  private sortHandle(arr: IoCompletionTimes[], ioCompletionTimesKey: string, type: number): void {
263    arr.sort((ioCompletionTimesA, ioCompletionTimesB): number => {
264      if (ioCompletionTimesKey === 'startTsStr') {
265        return type === 1
266          ? ioCompletionTimesA.startTs - ioCompletionTimesB.startTs
267          : ioCompletionTimesB.startTs - ioCompletionTimesA.startTs;
268      } else if (ioCompletionTimesKey === 'durStr') {
269        return type === 1
270          ? ioCompletionTimesA.dur - ioCompletionTimesB.dur
271          : ioCompletionTimesB.dur - ioCompletionTimesA.dur;
272      } else if (ioCompletionTimesKey === 'process') {
273        return this.sortProcessCase(ioCompletionTimesA, ioCompletionTimesB, type);
274      } else if (ioCompletionTimesKey === 'durPer4kStr') {
275        return type === 1
276          ? ioCompletionTimesA.durPer4k - ioCompletionTimesB.durPer4k
277          : ioCompletionTimesB.durPer4k - ioCompletionTimesA.durPer4k;
278      } else if (ioCompletionTimesKey === 'thread') {
279        return this.sortThreadCase(ioCompletionTimesA, ioCompletionTimesB, type);
280      } else if (ioCompletionTimesKey === 'operation') {
281        return this.sortOperationCase(ioCompletionTimesA, ioCompletionTimesB, type);
282      } else if (ioCompletionTimesKey === 'sizeStr') {
283        return type === 1
284          ? ioCompletionTimesA.size - ioCompletionTimesB.size
285          : ioCompletionTimesB.size - ioCompletionTimesA.size;
286      } else if (ioCompletionTimesKey === 'tier') {
287        return type === 1
288          ? ioCompletionTimesA.tier - ioCompletionTimesB.tier
289          : ioCompletionTimesB.tier - ioCompletionTimesA.tier;
290      } else {
291        return 0;
292      }
293    });
294  }
295
296  private sortOperationCase(
297    ioCompletionTimesA: IoCompletionTimes,
298    ioCompletionTimesB: IoCompletionTimes,
299    type: number
300  ): number {
301    if (ioCompletionTimesA.operation > ioCompletionTimesB.operation) {
302      return type === 2 ? 1 : -1;
303    } else if (ioCompletionTimesA.operation === ioCompletionTimesB.operation) {
304      return 0;
305    } else {
306      return type === 2 ? -1 : 1;
307    }
308  }
309
310  private sortThreadCase(
311    ioCompletionTimesA: IoCompletionTimes,
312    ioCompletionTimesB: IoCompletionTimes,
313    type: number
314  ): number {
315    if (ioCompletionTimesA.thread > ioCompletionTimesB.thread) {
316      return type === 2 ? 1 : -1;
317    } else if (ioCompletionTimesA.thread === ioCompletionTimesB.thread) {
318      return 0;
319    } else {
320      return type === 2 ? -1 : 1;
321    }
322  }
323
324  private sortProcessCase(
325    ioCompletionTimesA: IoCompletionTimes,
326    ioCompletionTimesB: IoCompletionTimes,
327    type: number
328  ): number {
329    if (ioCompletionTimesA.process > ioCompletionTimesB.process) {
330      return type === 2 ? 1 : -1;
331    } else if (ioCompletionTimesA.process === ioCompletionTimesB.process) {
332      return 0;
333    } else {
334      return type === 2 ? -1 : 1;
335    }
336  }
337
338  initHtml(): string {
339    return TabPaneIoCompletionTimesHtml;
340  }
341}
342