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.js"; 17import {LitTable} from "../../../../../base-ui/table/lit-table.js"; 18import {SelectionParam} from "../../../../bean/BoxSelection.js"; 19import { 20 getTabPaneVirtualMemoryStatisticsData, 21} from "../../../../database/SqlLite.js"; 22import {Utils} from "../../base/Utils.js"; 23import {LitProgressBar} from "../../../../../base-ui/progress-bar/LitProgressBar.js"; 24import {TabPaneFilter} from "../TabPaneFilter.js"; 25import "../TabPaneFilter.js"; 26import {VM_TYPE_MAP} from "../../../../database/logic-worker/ProcedureLogicWorkerFileSystem.js"; 27 28@element('tabpane-virtual-memory-statistics') 29export class TabPaneVirtualMemoryStatistics extends BaseElement { 30 private tbl: LitTable | null | undefined; 31 private range: HTMLLabelElement | null | undefined; 32 private loadDataInCache: boolean = true; 33 private selectionParam:SelectionParam | null | undefined; 34 private progressEL:LitProgressBar | null | undefined; 35 private filter: TabPaneFilter | null | undefined; 36 private loadingPage:any; 37 private loadingList:number[] = []; 38 private source: Array<any> = []; 39 private typeList: Array<string> = ["OPEN", "CLOSE", "READ" , "WRITE"]; 40 private sortKey: string = ""; 41 private sortType: number = 0; 42 private resultData: Array<any> = []; 43 44 set data(val: SelectionParam | any) { 45 if(val == this.selectionParam){ 46 return; 47 } 48 this.progressEL!.loading = true 49 this.loadingPage.style.visibility = "visible" 50 this.selectionParam = val; 51 // @ts-ignore 52 this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 20) + "px" 53 this.queryDataByDB(val) 54 } 55 56 initElements(): void { 57 this.progressEL = this.shadowRoot!.querySelector<LitProgressBar>('.progress') 58 this.loadingPage = this.shadowRoot!.querySelector('.loading'); 59 this.tbl = this.shadowRoot!.querySelector<LitTable>('#tb-states'); 60 this.tbl!.addEventListener('column-click', (evt) => { 61 // @ts-ignore 62 this.sortKey = evt.detail.key 63 // @ts-ignore 64 this.sortType = evt.detail.sort; 65 66 let newSource = JSON.parse(JSON.stringify(this.source)); 67 if (this.sortType != 0 && newSource.length > 0) this.sortTable(newSource[0],this.sortKey); 68 this.tbl!.recycleDataSource = newSource; 69 }) 70 this.filter = this.shadowRoot!.querySelector<TabPaneFilter>("#filter"); 71 this.filter!.getStatisticsTypeData((type)=>{ 72 if (type=="operation") { 73 this.sortStatus(this.resultData,"ipid","itid") 74 }else { 75 this.sortStatus(this.resultData,"type","ipid") 76 } 77 this.tbl!.shadowRoot!.querySelector("div > div.thead > div > div:nth-child(1) > label")!.textContent = type=="operation"?"Process/Thread/Operation":"Operation/Process/Thread" 78 }) 79 80 } 81 82 connectedCallback() { 83 super.connectedCallback(); 84 new ResizeObserver((entries) => { 85 if (this.parentElement!.clientHeight != 0) { 86 // @ts-ignore 87 this.tbl!.shadowRoot!.querySelector(".table").style.height = (this.parentElement!.clientHeight - 10 -31) + "px" 88 this.tbl!.reMeauseHeight() 89 this.loadingPage.style.height = (this.parentElement!.clientHeight - 24) + "px" 90 } 91 }).observe(this.parentElement!); 92 } 93 94 getInitData(item:any,nameTitle:any = "pname",subtitle:any = null){ 95 // @ts-ignore 96 let title = (nameTitle == "type")?VM_TYPE_MAP[item[nameTitle]]:item[nameTitle]; 97 return { 98 ...item, 99 title : title+(subtitle?("("+item[subtitle]+")"):""), 100 allDuration : Utils.getProbablyTime(item.allDuration), 101 minDuration : Utils.getProbablyTime(item.minDuration), 102 maxDuration : Utils.getProbablyTime(item.maxDuration), 103 avgDuration : Utils.getProbablyTime(item.avgDuration), 104 node:{...item,children:[]}, 105 } 106 } 107 108 queryDataByDB(val: SelectionParam | any) { 109 this.loadingList.push(1) 110 this.progressEL!.loading = true 111 this.loadingPage.style.visibility = "visible"; 112 getTabPaneVirtualMemoryStatisticsData(val.leftNs + val.recordStartNs,val.rightNs + val.recordStartNs).then(result => { 113 this.loadingList.splice(0,1) 114 if(this.loadingList.length == 0) { 115 this.progressEL!.loading = false 116 this.loadingPage.style.visibility = "hidden" 117 } 118 this.resultData = JSON.parse(JSON.stringify(result)); 119 this.sortStatus(result,"type","ipid") 120 }) 121 } 122 123 sortStatus(result:Array<any>,firstLevel:string,secondLevel:string){ 124 let fatherMap = new Map<any,any>(); 125 let childMap = new Map<any,any>(); 126 let allNode:any = { 127 title:"All", 128 count:0, 129 allDuration:0, 130 minDuration:0, 131 maxDuration:0, 132 avgDuration:"", 133 children:[], 134 }; 135 result.forEach((item,idx)=>{ 136 if (childMap.has(item[firstLevel]+"_"+item[secondLevel])) { 137 let obj1 = childMap.get(item[firstLevel]+"_"+item[secondLevel]); 138 obj1.count += item.count; 139 obj1.allDuration += item.allDuration; 140 obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; 141 obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; 142 obj1.children.push(this.getInitData(item,firstLevel=="type"?"tname":"type",firstLevel=="type"?"tid":null)); 143 }else { 144 childMap.set(item[firstLevel]+"_"+item[secondLevel],{ 145 ...item, 146 children:[this.getInitData(item,firstLevel=="type"?"tname":"type",firstLevel=="type"?"tid":null)] 147 }) 148 } 149 150 if (fatherMap.has(item[firstLevel])) { 151 let obj1 = fatherMap.get(item[firstLevel]); 152 obj1.count += item.count; 153 obj1.allDuration += item.allDuration; 154 obj1.minDuration = obj1.minDuration<=item.minDuration?obj1.minDuration:item.minDuration; 155 obj1.maxDuration = obj1.maxDuration>=item.maxDuration?obj1.maxDuration:item.maxDuration; 156 obj1.children.push(this.getInitData(item)); 157 }else { 158 fatherMap.set(item[firstLevel],{ 159 ...item, 160 children:[this.getInitData(item)] 161 }) 162 } 163 if (idx == 0) { 164 allNode.minDuration = item.minDuration; 165 }else { 166 allNode.minDuration = allNode.minDuration<=item.minDuration?allNode.minDuration:item.minDuration; 167 } 168 allNode.count += item.count; 169 allNode.allDuration += item.allDuration; 170 allNode.maxDuration = allNode.maxDuration>=item.maxDuration?allNode.maxDuration:item.maxDuration; 171 }) 172 173 for (let ks of fatherMap.keys()) { 174 let sp = fatherMap.get(ks) 175 sp!.children = []; 176 sp.avgDuration = sp.allDuration/sp.count; 177 let node = this.getInitData(sp,firstLevel=="type"?"type":"pname",firstLevel=="type"?null:"pid"); 178 node.path = {type:null,tid:null,pid:null,value:node.title} 179 node.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; 180 for (let kst of childMap.keys()) { 181 if (kst.startsWith(ks + "_")) { 182 let spt = childMap.get(kst) 183 let data = this.getInitData(spt!,firstLevel=="type"?"pname":"tname",firstLevel=="type"?"pid":"tid") 184 data.path = {type:null,tid:null,pid:null,value:"All-"+node.title+"-"+data.title} 185 data.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; 186 data.path[firstLevel=="type"?"pid":"tid"] = data[firstLevel=="type"?"pid":"tid"]; 187 data.children.forEach((e:any)=>{ 188 e.path = {type:null,tid:null,pid:null,value:"All-"+node.title+"-"+data.title+"-"+e.title} 189 e.path[firstLevel=="type"?"type":"pid"] = node[firstLevel=="type"?"type":"pid"]; 190 e.path[firstLevel=="type"?"pid":"tid"] = data[firstLevel=="type"?"pid":"tid"]; 191 e.path[firstLevel=="type"?"tid":"type"] = e[firstLevel=="type"?"tid":"type"]; 192 }) 193 sp!.children.push(data); 194 } 195 } 196 allNode.children.push(node) 197 } 198 199 allNode.avgDuration = allNode.allDuration/allNode.count; 200 allNode = this.getInitData(allNode); 201 allNode.title = "All"; 202 allNode.path = {type:null,tid:null,pid:null,value:"All"}; 203 this.source = result.length > 0 ? [allNode] : []; 204 let newSource = JSON.parse(JSON.stringify(this.source)); 205 if (this.sortType != 0 && result.length > 0) this.sortTable(newSource[0],this.sortKey); 206 this.tbl!.recycleDataSource = newSource; 207 } 208 209 sortTable(allNode:any,key:string){ 210 allNode.children.sort((a:any, b:any) => { 211 if (this.sortType == 1) { 212 return a.node[key] - b.node[key] 213 }else if (this.sortType == 2) { 214 return b.node[key] - a.node[key] 215 } 216 }); 217 allNode.children.forEach((item:any)=>{ 218 item.children.sort((a:any, b:any) => { 219 if (this.sortType == 1) { 220 return a.node[key] - b.node[key] 221 }else if (this.sortType == 2) { 222 return b.node[key] - a.node[key] 223 } 224 }) 225 item.children.forEach((i:any)=>{ 226 i.children.sort((a:any, b:any) => { 227 if (this.sortType == 1) { 228 return a.node[key] - b.node[key] 229 }else if (this.sortType == 2) { 230 return b.node[key] - a.node[key] 231 } 232 }) 233 }); 234 }); 235 } 236 237 initHtml(): string { 238 return ` 239 <style> 240 :host{ 241 display: flex; 242 flex-direction: column; 243 padding: 10px 10px 0 10px; 244 } 245 .progress{ 246 bottom: 5px; 247 position: absolute; 248 height: 1px; 249 left: 0; 250 right: 0; 251 } 252 .loading{ 253 bottom: 0; 254 position: absolute; 255 left: 0; 256 right: 0; 257 width:100%; 258 background:transparent; 259 z-index: 999999; 260 } 261 </style> 262 <lit-table id="tb-states" style="height: auto" tree> 263 <lit-table-column width="20%" title="Operation/Process/Thread" data-index="title" key="title" align="flex-start"> 264 </lit-table-column> 265 <lit-table-column width="1fr" title="Count" data-index="count" key="count" align="flex-start" order> 266 </lit-table-column> 267 <lit-table-column width="1fr" title="Duration" data-index="allDuration" key="allDuration" align="flex-start" order> 268 </lit-table-column> 269 <lit-table-column width="1fr" title="Min Duration" data-index="minDuration" key="minDuration" align="flex-start" order> 270 </lit-table-column> 271 <lit-table-column width="1fr" title="Avg Duration" data-index="avgDuration" key="avgDuration" align="flex-start" order> 272 </lit-table-column> 273 <lit-table-column width="1fr" title="Max Duration" data-index="maxDuration" key="maxDuration" align="flex-start" order> 274 </lit-table-column> 275 </lit-table> 276 <lit-progress-bar class="progress"></lit-progress-bar> 277 <tab-pane-filter id="filter" sort></tab-pane-filter> 278 <div class="loading"></div> 279 `; 280 } 281} 282