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 { type LitTable } from '../../../../../base-ui/table/lit-table'; 18import { type SelectionParam } from '../../../../bean/BoxSelection'; 19import { MemoryConfig } from '../../../../bean/MemoryConfig'; 20import { Utils } from '../../base/Utils'; 21import { resizeObserver } from '../SheetUtils'; 22import { querySysPurgeableTab } from '../../../../database/sql/Ability.sql'; 23import { queryProcessPurgeableTab } from '../../../../database/sql/ProcessThread.sql'; 24 25@element('tabpane-purg-total') 26export class TabPanePurgTotal extends BaseElement { 27 private purgeableTotalTable: LitTable | null | undefined; 28 private purgeableTotalSource: Array<PurgeableTabStruct> = []; 29 private tabTitle: HTMLDivElement | undefined | null; 30 private purgTotalTimeRange: HTMLLabelElement | undefined | null; 31 private sortKey = 'avgSize'; 32 private sortType = 2; 33 34 set data(selection: SelectionParam) { 35 if (this.purgeableTotalTable) { 36 //@ts-ignore 37 this.purgeableTotalTable.shadowRoot?.querySelector('.table').style.height = `${ 38 this.parentElement!.clientHeight - 45 39 }px`; 40 } 41 this.init(); 42 this.purgTotalTimeRange!.textContent = 43 'Selected range: ' + ((selection.rightNs - selection.leftNs) / 1000000.0).toFixed(5) + ' ms'; 44 this.purgeableTotalTable!.loading = true; 45 this.purgeableTotalTable!.recycleDataSource = []; 46 // 框选了 Purgeable Total 47 if (selection.purgeableTotalAbility.length > 0) { 48 this.purgeableTotalSource = []; 49 querySysPurgeableTab( 50 selection.leftNs, 51 selection.rightNs, 52 (MemoryConfig.getInstance().interval * 1000000) / 5 53 ).then((purgeTotalResults) => { 54 this.purgeableTotalTable!.loading = false; 55 this.getPurgeableTotalSource(purgeTotalResults); 56 }); 57 } else if (selection.purgeableTotalVM.length > 0) { 58 this.purgeableTotalSource = []; 59 queryProcessPurgeableTab( 60 selection.leftNs, 61 selection.rightNs, 62 (MemoryConfig.getInstance().interval * 1000000) / 5, 63 MemoryConfig.getInstance().iPid 64 ).then((results) => { 65 this.purgeableTotalTable!.loading = false; 66 this.getPurgeableTotalSource(results); 67 }); 68 } 69 } 70 71 getPurgeableTotalSource(results: unknown): void { 72 // @ts-ignore 73 if (results.length > 0) { 74 // @ts-ignore 75 for (let i = 0; i < results.length; i++) { 76 // @ts-ignore 77 this.purgeableTotalSource.push( 78 // @ts-ignore 79 this.toTabStruct(results[i].name, results[i].maxSize, results[i].minSize, results[i].avgSize) 80 ); 81 } 82 this.sortByColumn({ key: this.sortKey, sort: this.sortType }); 83 let total = this.totalData(this.purgeableTotalSource); 84 this.purgeableTotalSource.unshift(total); 85 this.purgeableTotalTable!.recycleDataSource = this.purgeableTotalSource; 86 this.purgeableTotalSource.shift(); 87 } else { 88 this.purgeableTotalSource = []; 89 this.purgeableTotalTable!.recycleDataSource = []; 90 } 91 } 92 93 private init(): void { 94 const thTable = this.tabTitle!.querySelector('.th'); 95 const purgeTotalTblNode = thTable!.querySelectorAll('div'); 96 if (this.tabTitle!.hasAttribute('sort')) { 97 this.tabTitle!.removeAttribute('sort'); 98 purgeTotalTblNode.forEach((item) => { 99 item.querySelectorAll('svg').forEach((svg) => { 100 svg.style.display = 'none'; 101 }); 102 }); 103 } 104 this.sortKey = 'avgSize'; 105 this.sortType = 2; 106 } 107 108 private toTabStruct(type: string, maxSize: number, minSize: number, avgSize: number): PurgeableTabStruct { 109 const tabStruct = new PurgeableTabStruct( 110 type, 111 maxSize, 112 minSize, 113 avgSize, 114 Utils.getBinaryByteWithUnit(avgSize), 115 Utils.getBinaryByteWithUnit(maxSize), 116 Utils.getBinaryByteWithUnit(minSize) 117 ); 118 return tabStruct; 119 } 120 121 private totalData(source: Array<PurgeableTabStruct>): PurgeableTabStruct { 122 // 计算总的time作为表格的第一行显示 123 let totalAvg = 0; 124 let totalMax = 0; 125 let totalMin = 0; 126 for (let item of source) { 127 totalAvg += item.avgSize; 128 totalMax += item.maxSize; 129 totalMin += item.minSize; 130 } 131 let totalData = this.toTabStruct('Total', totalAvg, totalMax, totalMin); 132 return totalData; 133 } 134 135 private sortByColumn(detail: unknown): void { 136 // @ts-ignore 137 function compare(key, sort, type) { 138 return function (purgeTotalLeftData: unknown, purgeTotalRightData: unknown) { 139 // 不管哪一列的排序方式是0(默认排序),都按照avgSize列从大到小排序 140 if (sort === 0) { 141 sort = 2; 142 key = 'avgSize'; 143 type = 'number'; 144 } 145 if (type === 'number') { 146 // @ts-ignore 147 return sort === 2 // @ts-ignore 148 ? parseFloat(purgeTotalRightData[key]) - parseFloat(purgeTotalLeftData[key]) // @ts-ignore 149 : parseFloat(purgeTotalLeftData[key]) - parseFloat(purgeTotalRightData[key]); 150 } else { 151 if (sort === 2) { 152 // @ts-ignore 153 return purgeTotalRightData[key].toString().localeCompare(purgeTotalLeftData[key].toString()); 154 } else { 155 // @ts-ignore 156 return purgeTotalLeftData[key].toString().localeCompare(purgeTotalRightData[key].toString()); 157 } 158 } 159 }; 160 } 161 // @ts-ignore 162 if (detail.key === 'type') { 163 // @ts-ignore 164 this.purgeableTotalSource.sort(compare(detail.key, detail.sort, 'string')); 165 } else { 166 // @ts-ignore 167 this.purgeableTotalSource.sort(compare(detail.key, detail.sort, 'number')); 168 } 169 let total = this.totalData(this.purgeableTotalSource); 170 this.purgeableTotalSource.unshift(total); 171 this.purgeableTotalTable!.recycleDataSource = this.purgeableTotalSource; 172 this.purgeableTotalSource.shift(); 173 } 174 175 initElements(): void { 176 this.purgeableTotalTable = this.shadowRoot?.querySelector<LitTable>('#tb-purgeable-total'); 177 this.tabTitle = this.purgeableTotalTable!.shadowRoot?.querySelector('.thead') as HTMLDivElement; 178 this.purgTotalTimeRange = this.shadowRoot?.querySelector('#purg-total-time-range') as HTMLLabelElement; 179 this.purgeableTotalTable!.addEventListener('column-click', (evt: unknown) => { 180 // @ts-ignore 181 this.sortKey = evt.detail.key; // @ts-ignore 182 this.sortType = evt.detail.sort; 183 // @ts-ignore 184 this.sortByColumn(evt.detail); 185 }); 186 } 187 188 connectedCallback(): void { 189 super.connectedCallback(); 190 resizeObserver(this.parentElement!, this.purgeableTotalTable!); 191 } 192 193 initHtml(): string { 194 return ` 195 <style> 196 :host{ 197 display: flex; 198 flex-direction: column; 199 padding: 10px 10px; 200 } 201 .purg-total-label{ 202 display: flex; 203 height: 20px; 204 align-items: center; 205 flex-direction: row; 206 margin-bottom: 5px; 207 } 208 #purg-total-time-range{ 209 width: auto; 210 text-align: end; 211 font-size: 10pt; 212 } 213 </style> 214 <div class="purg-total-label"> 215 <div style="flex: 1"></div> 216 <label id="purg-total-time-range">Selected range:0.0 ms</label> 217 </div> 218 <lit-table id="tb-purgeable-total" style="height: auto"> 219 <lit-table-column width="1fr" title="Type" data-index="type" key="type" align="flex-start" order> 220 </lit-table-column> 221 <lit-table-column width="1fr" title="AvgSize" data-index="avgSizeStr" key="avgSize" align="flex-start" order> 222 </lit-table-column> 223 <lit-table-column width="1fr" title="MaxSize" data-index="maxSizeStr" key="maxSize" align="flex-start" order> 224 </lit-table-column> 225 <lit-table-column width="1fr" title="MinSize" data-index="minSizeStr" key="minSize" align="flex-start" order> 226 </lit-table-column> 227 </lit-table> 228 `; 229 } 230} 231 232export class PurgeableTabStruct { 233 type: string; 234 avgSize: number; 235 maxSize: number; 236 minSize: number; 237 avgSizeStr: string; 238 maxSizeStr: string; 239 minSizeStr: string; 240 241 constructor( 242 type: string, 243 avgSize: number, 244 maxSize: number, 245 minSize: number, 246 avgSizeStr: string, 247 maxSizeStr: string, 248 minSizeStr: string 249 ) { 250 this.type = type; 251 this.avgSize = avgSize; 252 this.maxSize = maxSize; 253 this.minSize = minSize; 254 this.avgSizeStr = avgSizeStr; 255 this.maxSizeStr = maxSizeStr; 256 this.minSizeStr = minSizeStr; 257 } 258} 259