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