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