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 { LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; 19import { FrameChart } from '../../../chart/FrameChart'; 20import { SelectionParam } from '../../../../bean/BoxSelection'; 21import { ChartMode } from '../../../../bean/FrameChartStruct'; 22import { FilterData, TabPaneFilter } from '../TabPaneFilter'; 23import { procedurePool } from '../../../../database/Procedure'; 24import { MerageBean } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; 25import { showButtonMenu } from '../SheetUtils'; 26import { CallTreeLevelStruct } from '../../../../bean/EbpfStruct'; 27import '../../../../../base-ui/headline/lit-headline'; 28import { LitHeadLine } from '../../../../../base-ui/headline/lit-headline'; 29import { NUM_3, NUM_4 } from '../../../../bean/NumBean'; 30import { TabPaneCallTreeHtml } from './TabPaneCallTree.html'; 31 32const InvertOptionIndex: number = 0; 33const hideEventOptionIndex: number = 2; 34const hideThreadOptionIndex: number = 3; 35 36@element('tabpane-calltree') 37export class TabPaneCallTree extends BaseElement { 38 public queryFuncName: string = ''; 39 public procedureAction: string = ''; 40 private callTreeTbl: LitTable | null | undefined; 41 private callTreeTbr: LitTable | null | undefined; 42 private callTreeProgressEL: LitProgressBar | null | undefined; 43 private callTreeRightSource: Array<MerageBean> = []; 44 private callTreeFilter: TabPaneFilter | null | undefined; 45 private callTreeDataSource: unknown[] = []; 46 private callTreeSortKey: string = 'weight'; 47 private callTreeSortType: number = 0; 48 private callTreeSelectedData: unknown = undefined; 49 private frameChart: FrameChart | null | undefined; 50 private isChartShow: boolean = false; 51 private systmeRuleName: string = '/system/'; 52 private callTreeNumRuleName: string = '/max/min/'; 53 private needShowMenu: boolean = true; 54 private searchValue: string = ''; 55 private loadingList: number[] = []; 56 private loadingPage: unknown; 57 private currentSelection: SelectionParam | undefined; 58 private flameChartMode: ChartMode = ChartMode.Duration; 59 private currentCallTreeDataSource: Array<MerageBean> = []; 60 private currentRowClickData: unknown; 61 private initWidth: number = 0; 62 private _pieTitle: string = ''; 63 private _cWidth: number = 0; 64 private _currentCallTreeLevel: number = 0; 65 private _rowClickData: unknown = undefined; 66 private callTreeLevel: CallTreeLevelStruct | undefined | null; 67 private callTreeHeadLine: LitHeadLine | null | undefined; 68 69 set pieTitle(value: string) { 70 this._pieTitle = value; 71 if (this._pieTitle.length > 0) { 72 this.callTreeHeadLine!.isShow = true; 73 this.callTreeHeadLine!.titleTxt = this._pieTitle; 74 this.callTreeHeadLine!.closeCallback = (): void => { 75 this.restore(); 76 }; 77 } 78 } 79 80 set cWidth(value: number) { 81 this._cWidth = value; 82 } 83 84 set currentCallTreeLevel(value: number) { 85 this._currentCallTreeLevel = value; 86 } 87 88 set rowClickData(value: unknown) { 89 this._rowClickData = value; 90 } 91 92 set data(callTreeSelection: SelectionParam | unknown) { 93 if (callTreeSelection !== this.currentSelection && this._rowClickData === this.currentRowClickData) { 94 this._rowClickData = undefined; 95 } 96 if (callTreeSelection === this.currentSelection && !this.currentSelection?.isRowClick) { 97 return; 98 } 99 this.searchValue = ''; 100 this.initModeAndAction(); // @ts-ignore 101 this.currentSelection = callTreeSelection; 102 this.currentRowClickData = this._rowClickData; 103 this.callTreeTbl!.style.visibility = 'visible'; 104 if (this.parentElement!.clientHeight > this.callTreeFilter!.clientHeight) { 105 this.callTreeFilter!.style.display = 'flex'; 106 } else { 107 this.callTreeFilter!.style.display = 'none'; 108 } 109 procedurePool.submitWithName('logic0', 'fileSystem-reset', [], undefined, () => {}); 110 this.callTreeFilter!.initializeFilterTree(true, true, true); 111 this.callTreeFilter!.filterValue = ''; 112 this.callTreeProgressEL!.loading = true; // @ts-ignore 113 this.loadingPage.style.visibility = 'visible'; // @ts-ignore 114 this.getDataByWorkAndUpDateCanvas(callTreeSelection); 115 } 116 117 getDataByWorkAndUpDateCanvas(callTreeSelection: SelectionParam): void { 118 if (this.clientWidth === 0) { 119 this.initWidth = this._cWidth; 120 } else { 121 this.initWidth = this.clientWidth; 122 } 123 if (this._rowClickData && this.currentRowClickData !== undefined && this.currentSelection?.isRowClick) { 124 this.getCallTreeDataByPieLevel(); 125 } else { 126 this.callTreeHeadLine!.isShow = false; 127 this.getCallTreeData(callTreeSelection, this.initWidth); 128 } 129 } 130 131 private getCallTreeData(callTreeSelection: SelectionParam | unknown, initWidth: number): void { 132 this.getDataByWorker( 133 [ 134 { 135 funcName: 'setSearchValue', 136 funcArgs: [''], 137 }, 138 { 139 funcName: 'getCurrentDataFromDb', // @ts-ignore 140 funcArgs: [{ queryFuncName: this.queryFuncName, ...callTreeSelection }], 141 }, 142 ], 143 (results: unknown[]): void => { 144 this.setLTableData(results); 145 this.callTreeTbr!.recycleDataSource = []; 146 this.frameChart!.mode = this.flameChartMode; 147 this.frameChart?.updateCanvas(true, initWidth); // @ts-ignore 148 this.frameChart!.data = this.callTreeDataSource; // @ts-ignore 149 this.currentCallTreeDataSource = this.callTreeDataSource; 150 this.switchFlameChart(); 151 this.callTreeFilter!.icon = 'block'; 152 } 153 ); 154 } 155 156 /** 157 * 根据Analysis Tab饼图跳转过来的层级绘制对应的CallTree Tab火焰图和表格 158 */ 159 private getCallTreeDataByPieLevel(): void { 160 this.callTreeLevel = new CallTreeLevelStruct(); 161 this.callTreeLevel = { 162 // @ts-ignore 163 processId: this._rowClickData.pid, // @ts-ignore 164 threadId: this._rowClickData.tid, // @ts-ignore 165 typeId: this._rowClickData.type, // @ts-ignore 166 libId: this._rowClickData.libId, // @ts-ignore 167 symbolId: this._rowClickData.symbolId, 168 }; 169 let args = []; 170 args.push({ 171 funcName: 'getCurrentDataFromDb', 172 funcArgs: [this.currentSelection, this.callTreeLevel], 173 }); 174 // @ts-ignore 175 if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentCallTreeLevel === NUM_3) { 176 // @ts-ignore 177 this.callTreeLevel.libName = this._rowClickData.tableName; 178 args.push({ 179 funcName: 'showLibLevelData', 180 funcArgs: [this.callTreeLevel.libId, this.callTreeLevel.libName], 181 }); 182 } else if ( 183 this._rowClickData && // @ts-ignore 184 this._rowClickData.symbolId !== undefined && 185 this._currentCallTreeLevel === NUM_4 186 ) { 187 // @ts-ignore 188 this.callTreeLevel.symbolName = this._rowClickData.tableName; 189 args.push({ 190 funcName: 'showFunLevelData', 191 funcArgs: [this.callTreeLevel.symbolId, this.callTreeLevel.symbolName], 192 }); 193 } 194 195 this.getDataByWorker(args, (results: unknown[]): void => { 196 this.callTreeProgressEL!.loading = false; // @ts-ignore 197 this.loadingPage.style.visibility = 'hidden'; 198 this.setLTableData(results); 199 this.callTreeTbr!.recycleDataSource = []; 200 this.frameChart!.mode = this.flameChartMode; 201 this.frameChart?.updateCanvas(true, this.initWidth); // @ts-ignore 202 this.frameChart!.data = this.callTreeDataSource; // @ts-ignore 203 this.currentCallTreeDataSource = this.callTreeDataSource; 204 this.switchFlameChart(); 205 this.callTreeFilter!.icon = 'block'; 206 }); 207 } 208 209 private restore(): void { 210 this.searchValue = ''; 211 this.callTreeFilter!.filterValue = ''; 212 this.callTreeHeadLine!.isShow = false; 213 this._rowClickData = undefined; 214 this.getCallTreeData(this.currentSelection, this.initWidth); 215 } 216 217 initModeAndAction(): void { 218 if (this.procedureAction === '' && this.hasAttribute('action')) { 219 this.procedureAction = this.getAttribute('action') || ''; 220 } 221 if (this.hasAttribute('flame-mode')) { 222 let callTreeFlameMode = this.getAttribute('flame-mode'); 223 switch (callTreeFlameMode) { 224 case 'Byte': 225 this.flameChartMode = ChartMode.Byte; 226 break; 227 case 'Count': 228 this.flameChartMode = ChartMode.Count; 229 break; 230 case 'Duration': 231 this.flameChartMode = ChartMode.Duration; 232 break; 233 } 234 } 235 if (this.hasAttribute('query')) { 236 this.queryFuncName = this.getAttribute('query') || ''; 237 } 238 } 239 240 getParentTree(callTreeSrc: Array<MerageBean>, target: MerageBean, parents: Array<MerageBean>): boolean { 241 for (let callTreeBean of callTreeSrc) { 242 if (callTreeBean.id === target.id) { 243 parents.push(callTreeBean); 244 return true; 245 } else { 246 if (this.getParentTree(callTreeBean.children as Array<MerageBean>, target, parents)) { 247 parents.push(callTreeBean); 248 return true; 249 } 250 } 251 } 252 return false; 253 } 254 255 getChildTree(callTreeSrc: Array<MerageBean>, id: string, children: Array<MerageBean>): boolean { 256 for (let callTreeBean of callTreeSrc) { 257 if (callTreeBean.id === id && callTreeBean.children.length === 0) { 258 children.push(callTreeBean); 259 return true; 260 } else { 261 if (this.getChildTree(callTreeBean.children as Array<MerageBean>, id, children)) { 262 children.push(callTreeBean); 263 return true; 264 } 265 } 266 } 267 return false; 268 } 269 270 setRightTableData(bean: MerageBean): void { 271 let parents: Array<MerageBean> = []; 272 let children: Array<MerageBean> = []; // @ts-ignore 273 this.getParentTree(this.callTreeDataSource, bean, parents); 274 let maxId: string = bean.id; 275 let maxDur: number = 0; 276 277 function findMaxStack(bean: MerageBean): void { 278 if (bean.children.length === 0) { 279 if (bean.dur > maxDur) { 280 maxDur = bean.dur; 281 maxId = bean.id; 282 } 283 } else { 284 bean.children.map((callChild: unknown) => { 285 findMaxStack(<MerageBean>callChild); 286 }); 287 } 288 } 289 290 findMaxStack(bean); 291 this.getChildTree(bean.children as Array<MerageBean>, maxId, children); 292 let callTreeArr = parents.reverse().concat(children.reverse()); 293 for (let data of callTreeArr) { 294 data.type = data.lib.endsWith('.so.1') || data.lib.endsWith('.dll') || data.lib.endsWith('.so') ? 0 : 1; 295 } 296 let len = callTreeArr.length; 297 this.callTreeRightSource = callTreeArr; 298 this.callTreeTbr!.dataSource = len === 0 ? [] : callTreeArr; 299 } 300 301 connectedCallback(): void { 302 this.parentElement!.onscroll = (): void => { 303 this.frameChart!.tabPaneScrollTop = this.parentElement!.scrollTop; 304 }; 305 this.frameChart!.addChartClickListener((needShowMenu: boolean) => { 306 this.parentElement!.scrollTo(0, 0); 307 showButtonMenu(this.callTreeFilter, needShowMenu); 308 this.needShowMenu = needShowMenu; 309 }); 310 let filterHeight = 0; 311 new ResizeObserver((entries: ResizeObserverEntry[]): void => { 312 let callTreeTabFilter = this.shadowRoot!.querySelector('#filter') as HTMLElement; 313 if (callTreeTabFilter.clientHeight > 0) { 314 filterHeight = callTreeTabFilter.clientHeight; 315 } 316 if (this.parentElement!.clientHeight > filterHeight) { 317 callTreeTabFilter.style.display = 'flex'; 318 } else { 319 callTreeTabFilter.style.display = 'none'; 320 } 321 if (this.callTreeTbl!.style.visibility === 'hidden') { 322 callTreeTabFilter.style.display = 'none'; 323 } 324 if (this.parentElement?.clientHeight !== 0) { 325 if (this.isChartShow) { 326 this.frameChart?.updateCanvas(false, entries[0].contentRect.width); 327 this.frameChart?.calculateChartData(); 328 } 329 let headLineHeight = 0; 330 if (this.callTreeHeadLine?.isShow) { 331 headLineHeight = this.callTreeHeadLine!.clientHeight; 332 } 333 if (this.callTreeTbl) { 334 // @ts-ignore 335 this.callTreeTbl.shadowRoot.querySelector('.table').style.height = `${ 336 this.parentElement!.clientHeight - 10 - 35 - headLineHeight 337 }px`; 338 this.callTreeTbl.reMeauseHeight(); 339 } 340 if (this.callTreeTbr) { 341 // @ts-ignore 342 this.callTreeTbr.shadowRoot.querySelector('.table').style.height = `${ 343 this.parentElement!.clientHeight - 45 - 21 - headLineHeight 344 }px`; 345 this.callTreeTbr.reMeauseHeight(); 346 } // @ts-ignore 347 this.loadingPage.style.height = `${this.parentElement!.clientHeight - 24}px`; 348 } 349 }).observe(this.parentElement!); 350 } 351 352 initElements(): void { 353 this.callTreeHeadLine = this.shadowRoot?.querySelector<LitHeadLine>('.titleBox'); 354 this.callTreeTbl = this.shadowRoot?.querySelector<LitTable>('#tb-calltree'); 355 this.callTreeProgressEL = this.shadowRoot?.querySelector('.call-tree-progress') as LitProgressBar; 356 this.frameChart = this.shadowRoot?.querySelector<FrameChart>('#framechart'); 357 this.loadingPage = this.shadowRoot?.querySelector('.call-tree-loading'); 358 this.callTreeTbl!.rememberScrollTop = true; 359 this.callTreeFilter = this.shadowRoot?.querySelector<TabPaneFilter>('#filter'); 360 this.callTreeFilter!.disabledTransfer(true); 361 this.addEventListener('contextmenu', (event): void => { 362 event.preventDefault(); // 阻止默认的上下文菜单弹框 363 }); 364 this.rowClickEvent(); 365 let boundFilterFunc = this.filterFunc.bind(this); 366 this.callTreeFilter!.getDataLibrary(boundFilterFunc); 367 this.callTreeFilter!.getDataMining(boundFilterFunc); 368 this.handleCallTreeData(); 369 this.handleConstraintsData(); 370 this.handleFilterData(); 371 this.callTreeColumnClick(); 372 } 373 374 private filterFunc(data: unknown): void { 375 let callTreeFuncArgs: unknown[] = []; // @ts-ignore 376 if (data.type === 'check') { 377 this.handleCheckType(data, callTreeFuncArgs); // @ts-ignore 378 } else if (data.type === 'select') { 379 this.handleSelectType(callTreeFuncArgs, data); // @ts-ignore 380 } else if (data.type === 'button') { 381 // @ts-ignore 382 if (data.item === 'symbol') { 383 // @ts-ignore 384 if (this.callTreeSelectedData && !this.callTreeSelectedData.canCharge) { 385 return; 386 } 387 if (this.callTreeSelectedData !== undefined) { 388 this.handleSymbolCase(data, callTreeFuncArgs); 389 } else { 390 return; 391 } // @ts-ignore 392 } else if (data.item === 'library') { 393 // @ts-ignore 394 if (this.callTreeSelectedData && !this.callTreeSelectedData.canCharge) { 395 return; 396 } // @ts-ignore 397 if (this.callTreeSelectedData !== undefined && this.callTreeSelectedData.lib !== '') { 398 this.handleLibraryCase(data, callTreeFuncArgs); 399 } else { 400 return; 401 } // @ts-ignore 402 } else if (data.item === 'restore') { 403 this.handleRestoreCase(data, callTreeFuncArgs); 404 } 405 } 406 this.performDataProcessing(callTreeFuncArgs); 407 } 408 409 private handleLibraryCase(data: unknown, callTreeFuncArgs: unknown[]): void { 410 // @ts-ignore 411 this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.lib }, data.item); 412 callTreeFuncArgs.push({ 413 funcName: 'splitTree', // @ts-ignore 414 funcArgs: [this.callTreeSelectedData.lib, false, false], 415 }); 416 } 417 418 private handleSymbolCase(data: unknown, callTreeFuncArgs: unknown[]): void { 419 // @ts-ignore 420 this.callTreeFilter!.addDataMining({ name: this.callTreeSelectedData.symbol }, data.item); 421 callTreeFuncArgs.push({ 422 funcName: 'splitTree', // @ts-ignore 423 funcArgs: [this.callTreeSelectedData.symbol, false, true], 424 }); 425 } 426 427 private callTreeColumnClick(): void { 428 this.callTreeTbl!.addEventListener('column-click', (evt: Event): void => { 429 // @ts-ignore 430 this.callTreeSortKey = evt.detail.key; 431 // @ts-ignore 432 this.callTreeSortType = evt.detail.sort; 433 // @ts-ignore 434 this.setLTableData(this.callTreeDataSource); // @ts-ignore 435 this.frameChart!.data = this.callTreeDataSource; 436 }); 437 } 438 439 private performDataProcessing(callTreeFuncArgs: unknown[]): void { 440 this.getDataByWorker(callTreeFuncArgs, (result: unknown[]): void => { 441 this.setLTableData(result); // @ts-ignore 442 this.frameChart!.data = this.callTreeDataSource; 443 if (this.isChartShow) { 444 this.frameChart?.calculateChartData(); 445 } 446 this.callTreeTbl!.move1px(); 447 if (this.callTreeSelectedData) { 448 // @ts-ignore 449 this.callTreeSelectedData.isSelected = false; 450 this.callTreeTbl?.clearAllSelection(this.callTreeSelectedData); 451 this.callTreeTbr!.recycleDataSource = []; 452 this.callTreeSelectedData = undefined; 453 } 454 }); 455 } 456 457 private handleRestoreCase(data: unknown, callTreeFuncArgs: unknown[]): void { 458 // @ts-ignore 459 if (data.remove !== undefined && data.remove.length > 0) { 460 // @ts-ignore 461 let list = data.remove.map((item: unknown) => { 462 // @ts-ignore 463 return item.name; 464 }); 465 callTreeFuncArgs.push({ 466 funcName: 'resotreAllNode', 467 funcArgs: [list], 468 }); 469 callTreeFuncArgs.push({ 470 funcName: 'resetAllNode', 471 funcArgs: [], 472 }); 473 list.forEach((symbol: string) => { 474 callTreeFuncArgs.push({ 475 funcName: 'clearSplitMapData', 476 funcArgs: [symbol], 477 }); 478 }); 479 } 480 } 481 482 private handleFilterData(): void { 483 this.callTreeFilter!.getFilterData((callTreeFilterData: FilterData) => { 484 if ( 485 (this.isChartShow && callTreeFilterData.icon === 'tree') || 486 (!this.isChartShow && callTreeFilterData.icon === 'block') 487 ) { 488 this.switchFlameChart(callTreeFilterData); 489 } else if (this.searchValue !== this.callTreeFilter!.filterValue) { 490 this.searchValue = this.callTreeFilter!.filterValue; 491 let callTreeArgs = [ 492 { 493 funcName: 'setSearchValue', 494 funcArgs: [this.searchValue], 495 }, 496 { 497 funcName: 'resetAllNode', 498 funcArgs: [], 499 }, 500 ]; 501 this.getDataByWorker(callTreeArgs, (result: unknown[]): void => { 502 this.callTreeTbl!.isSearch = true; 503 this.callTreeTbl!.setStatus(result, true); 504 this.setLTableData(result); // @ts-ignore 505 this.frameChart!.data = this.callTreeDataSource; 506 this.switchFlameChart(callTreeFilterData); 507 }); 508 } else { 509 this.callTreeTbl!.setStatus(this.callTreeDataSource, true); 510 this.setLTableData(this.callTreeDataSource); 511 this.switchFlameChart(callTreeFilterData); 512 } 513 }); 514 } 515 516 private handleConstraintsData(): void { 517 this.callTreeFilter!.getCallTreeConstraintsData((data: unknown) => { 518 let callTreeConstraintsArgs: unknown[] = [ 519 { 520 funcName: 'resotreAllNode', 521 funcArgs: [[this.callTreeNumRuleName]], 522 }, 523 { 524 funcName: 'clearSplitMapData', 525 funcArgs: [this.callTreeNumRuleName], 526 }, 527 ]; // @ts-ignore 528 if (data.checked) { 529 callTreeConstraintsArgs.push({ 530 funcName: 'hideNumMaxAndMin', // @ts-ignore 531 funcArgs: [parseInt(data.min), data.max], 532 }); 533 } 534 callTreeConstraintsArgs.push({ 535 funcName: 'resetAllNode', 536 funcArgs: [], 537 }); 538 this.getDataByWorker(callTreeConstraintsArgs, (result: unknown[]) => { 539 this.setLTableData(result); // @ts-ignore 540 this.frameChart!.data = this.callTreeDataSource; 541 if (this.isChartShow) { 542 this.frameChart?.calculateChartData(); 543 } 544 }); 545 }); 546 } 547 548 private handleCallTreeData(): void { 549 this.callTreeFilter!.getCallTreeData((data: unknown) => { 550 // @ts-ignore 551 if ([InvertOptionIndex, hideThreadOptionIndex, hideEventOptionIndex].includes(data.value)) { 552 this.refreshAllNode({ 553 ...this.callTreeFilter!.getFilterTreeData(), // @ts-ignore 554 callTree: data.checks, 555 }); 556 } else { 557 let callTreeArgs: unknown[] = []; // @ts-ignore 558 if (data.checks[1]) { 559 callTreeArgs.push({ 560 funcName: 'hideSystemLibrary', 561 funcArgs: [true], 562 }); 563 callTreeArgs.push({ 564 funcName: 'resetAllNode', 565 funcArgs: [], 566 }); 567 } else { 568 callTreeArgs.push({ 569 funcName: 'resotreAllNode', 570 funcArgs: [[this.systmeRuleName]], 571 }); 572 callTreeArgs.push({ 573 funcName: 'resetAllNode', 574 funcArgs: [], 575 }); 576 callTreeArgs.push({ 577 funcName: 'clearSplitMapData', 578 funcArgs: [this.systmeRuleName], 579 }); 580 } 581 this.getDataByWorker(callTreeArgs, (result: unknown[]) => { 582 this.setLTableData(result); // @ts-ignore 583 this.frameChart!.data = this.callTreeDataSource; 584 if (this.isChartShow) { 585 this.frameChart?.calculateChartData(); 586 } 587 }); 588 } 589 }); 590 } 591 592 private handleSelectType(callTreeFuncArgs: unknown[], data: unknown): void { 593 callTreeFuncArgs.push({ 594 funcName: 'resotreAllNode', // @ts-ignore 595 funcArgs: [[data.item.name]], 596 }); 597 callTreeFuncArgs.push({ 598 funcName: 'clearSplitMapData', // @ts-ignore 599 funcArgs: [data.item.name], 600 }); 601 callTreeFuncArgs.push({ 602 funcName: 'splitTree', // @ts-ignore 603 funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'], 604 }); 605 } 606 607 private handleCheckType(data: unknown, callTreeFuncArgs: unknown[]): void { 608 // @ts-ignore 609 if (data.item.checked) { 610 callTreeFuncArgs.push({ 611 funcName: 'splitTree', // @ts-ignore 612 funcArgs: [data.item.name, data.item.select === '0', data.item.type === 'symbol'], 613 }); 614 } else { 615 callTreeFuncArgs.push({ 616 funcName: 'resotreAllNode', // @ts-ignore 617 funcArgs: [[data.item.name]], 618 }); 619 callTreeFuncArgs.push({ 620 funcName: 'resetAllNode', 621 funcArgs: [], 622 }); 623 callTreeFuncArgs.push({ 624 funcName: 'clearSplitMapData', // @ts-ignore 625 funcArgs: [data.item.name], 626 }); 627 } 628 } 629 630 private rowClickEvent(): void { 631 this.callTreeTbl!.addEventListener('row-click', (evt: unknown) => { 632 // @ts-ignore 633 let data = evt.detail.data as MerageBean; 634 document.dispatchEvent( 635 new CustomEvent('number_calibration', { 636 detail: { time: data.tsArray, durations: data.durArray }, 637 }) 638 ); 639 this.setRightTableData(data); 640 data.isSelected = true; 641 this.callTreeSelectedData = data; 642 this.callTreeTbr?.clearAllSelection(data); 643 this.callTreeTbr?.setCurrentSelection(data); 644 // @ts-ignore 645 if ((evt.detail as unknown).callBack) { 646 // @ts-ignore 647 (evt.detail as unknown).callBack(true); 648 } 649 }); 650 this.callTreeTbr = this.shadowRoot?.querySelector<LitTable>('#tb-list'); 651 this.callTreeTbr!.addEventListener('row-click', (evt: unknown): void => { 652 // @ts-ignore 653 let data = evt.detail.data as MerageBean; 654 this.callTreeTbl?.clearAllSelection(data); // @ts-ignore 655 (data as unknown).isSelected = true; 656 this.callTreeTbl!.scrollToData(data); 657 // @ts-ignore 658 if ((evt.detail as unknown).callBack) { 659 // @ts-ignore 660 (evt.detail as unknown).callBack(true); 661 } 662 }); 663 } 664 665 switchFlameChart(data?: unknown): void { 666 let callTreePageTab = this.shadowRoot?.querySelector('#show_table'); 667 let callTreePageChart = this.shadowRoot?.querySelector('#show_chart'); // @ts-ignore 668 if (!data || data.icon === 'block') { 669 callTreePageChart?.setAttribute('class', 'show'); 670 callTreePageTab?.setAttribute('class', ''); 671 this.isChartShow = true; 672 this.callTreeFilter!.disabledMining = true; 673 showButtonMenu(this.callTreeFilter, this.needShowMenu); 674 this.frameChart?.calculateChartData(); // @ts-ignore 675 } else if (data.icon === 'tree') { 676 callTreePageChart?.setAttribute('class', ''); 677 callTreePageTab?.setAttribute('class', 'show'); 678 showButtonMenu(this.callTreeFilter, true); 679 this.isChartShow = false; 680 this.callTreeFilter!.disabledMining = false; 681 this.frameChart!.clearCanvas(); 682 this.callTreeTbl!.reMeauseHeight(); 683 } 684 } 685 686 refreshAllNode(filterData: unknown): void { 687 let callTreeArgs: unknown[] = []; // @ts-ignore 688 let isTopDown: boolean = !filterData.callTree[0]; // @ts-ignore 689 let isHideSystemLibrary = filterData.callTree[1]; // @ts-ignore 690 let isHideEvent: boolean = filterData.callTree[2]; // @ts-ignore 691 let isHideThread: boolean = filterData.callTree[3]; // @ts-ignore 692 let list = filterData.dataMining.concat(filterData.dataLibrary); 693 callTreeArgs.push({ funcName: 'hideThread', funcArgs: [isHideThread] }); 694 callTreeArgs.push({ funcName: 'hideEvent', funcArgs: [isHideEvent] }); 695 callTreeArgs.push({ funcName: 'getCallChainsBySampleIds', funcArgs: [isTopDown, this.queryFuncName] }); 696 this.callTreeTbr!.recycleDataSource = []; 697 if (isHideSystemLibrary) { 698 callTreeArgs.push({ funcName: 'hideSystemLibrary', funcArgs: [true] }); 699 } // @ts-ignore 700 if (filterData.callTreeConstraints.checked) { 701 callTreeArgs.push({ 702 funcName: 'hideNumMaxAndMin', // @ts-ignore 703 funcArgs: [parseInt(filterData.callTreeConstraints.inputs[0]), filterData.callTreeConstraints.inputs[1]], 704 }); 705 } 706 callTreeArgs.push({ funcName: 'splitAllProcess', funcArgs: [list] }); 707 callTreeArgs.push({ 708 funcName: 'resetAllNode', 709 funcArgs: [], 710 }); // @ts-ignore 711 if (this._rowClickData && this._rowClickData.libId !== undefined && this._currentCallTreeLevel === 3) { 712 callTreeArgs.push({ 713 funcName: 'showLibLevelData', 714 funcArgs: [this.callTreeLevel!.libId, this.callTreeLevel!.libName], 715 }); // @ts-ignore 716 } else if (this._rowClickData && this._rowClickData.symbolId !== undefined && this._currentCallTreeLevel === 4) { 717 callTreeArgs.push({ 718 funcName: 'showFunLevelData', 719 funcArgs: [this.callTreeLevel!.symbolId, this.callTreeLevel!.symbolName], 720 }); 721 } 722 this.getDataByWorker(callTreeArgs, (result: unknown[]): void => { 723 this.setLTableData(result); // @ts-ignore 724 this.frameChart!.data = this.callTreeDataSource; 725 if (this.isChartShow) { 726 this.frameChart?.calculateChartData(); 727 } 728 }); 729 } 730 731 setLTableData(resultData: unknown[]): void { 732 this.callTreeDataSource = this.sortCallFnTree(resultData); 733 this.callTreeTbl!.recycleDataSource = this.callTreeDataSource; 734 } 735 736 sortCallFnTree(arr: Array<unknown>): Array<unknown> { 737 let sortArr = arr.sort((compareFnA: unknown, compareFnB: unknown): number => { 738 if (this.callTreeSortKey === 'self') { 739 if (this.callTreeSortType === 0) { 740 // @ts-ignore 741 return compareFnB.dur - compareFnA.dur; 742 } else if (this.callTreeSortType === 1) { 743 // @ts-ignore 744 return compareFnA.selfDur - compareFnB.selfDur; 745 } else { 746 // @ts-ignore 747 return compareFnB.selfDur - compareFnA.selfDur; 748 } 749 } else { 750 if (this.callTreeSortType === 0) { 751 // @ts-ignore 752 return compareFnB.dur - compareFnA.dur; 753 } else if (this.callTreeSortType === 1) { 754 // @ts-ignore 755 return compareFnA.dur - compareFnB.dur; 756 } else { 757 // @ts-ignore 758 return compareFnB.dur - compareFnA.dur; 759 } 760 } 761 }); 762 sortArr.map((call: unknown): void => { 763 // @ts-ignore 764 call.children = this.sortCallFnTree(call.children); 765 }); 766 return sortArr; 767 } 768 769 getDataByWorker(args: unknown[], handler: Function): void { 770 this.loadingList.push(1); // @ts-ignore 771 this.loadingPage.style.visibility = 'visible'; 772 this.callTreeProgressEL!.loading = true; 773 procedurePool.submitWithName( 774 'logic0', 775 this.procedureAction, 776 { args, callType: this.queryFuncName }, 777 undefined, 778 (callTreeResults: unknown): void => { 779 handler(callTreeResults); 780 this.loadingList.splice(0, 1); 781 if (this.loadingList.length === 0) { 782 this.callTreeProgressEL!.loading = false; // @ts-ignore 783 this.loadingPage.style.visibility = 'hidden'; 784 } 785 } 786 ); 787 } 788 789 initHtml(): string { 790 return TabPaneCallTreeHtml; 791 } 792} 793