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