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 */ 15import { HeapDataInterface, ParseListener } from './HeapDataInterface.js'; 16import { AllocationFunction, FileType } from './model/UiStruct.js'; 17import { getTimeForLog } from './utils/Utils.js'; 18import { HeapNode, FileStruct } from './model/DatabaseStruct.js'; 19import { 20 queryHeapFile, 21 queryHeapInfo, 22 queryHeapNode, 23 queryHeapEdge, 24 queryHeapFunction, 25 queryHeapTraceNode, 26 queryHeapSample, 27 queryHeapString, 28} from '../trace/database/SqlLite.js'; 29import { info } from '../log/Log.js'; 30 31export class LoadDatabase { 32 private static loadDB: LoadDatabase; 33 private fileModule!: Array<FileStruct>; 34 35 static getInstance() { 36 if (!this.loadDB) { 37 this.loadDB = new LoadDatabase(); 38 } 39 return this.loadDB; 40 } 41 42 private async loadFile(listener: ParseListener) { 43 this.fileModule = new Array<FileStruct>(); 44 let result = await queryHeapFile(); 45 listener.process('start loading file ', 1); 46 for (let row of result) { 47 let fileStruct = new FileStruct(); 48 fileStruct.id = row.id; 49 fileStruct.name = row.name; 50 fileStruct.startTs = row.startTs; 51 fileStruct.endTs = row.endTs; 52 fileStruct.pid = row.pid; 53 fileStruct.size = row.size; 54 if (fileStruct.name.startsWith('Snapshot')) { 55 fileStruct.type = FileType.SNAPSHOT; 56 } else { 57 fileStruct.type = FileType.TIMELINE; 58 } 59 info(`read ${fileStruct.name} from db ${getTimeForLog()}`); 60 //fileStruct.profile.root_index = 0 61 await this.loadInfo(fileStruct); 62 await this.loadStrings(fileStruct); 63 await this.loadNode(fileStruct); 64 await this.loadEdge(fileStruct); 65 await this.loadTraceFunctionInfos(fileStruct); 66 await this.loadTraceTree(fileStruct); 67 await this.loadSamples(fileStruct); 68 let percent = Math.floor(50 / result.length) * (row.id + 1); 69 listener.process('loading file ' + fileStruct.name + ' from db ', percent); 70 info(`read ${fileStruct.name} from db Success ${getTimeForLog()}`); 71 this.fileModule.push(fileStruct); 72 } 73 listener.process('Loading completed ', 50); 74 let dataParse = HeapDataInterface.getInstance(); 75 dataParse.setPraseListener(listener); 76 dataParse.parseData(this.fileModule); 77 } 78 79 private async loadInfo(file: FileStruct) { 80 let result = await queryHeapInfo(file.id); 81 for (let row of result) { 82 if (row.key.includes('types')) continue; 83 switch (row.key) { 84 case 'node_count': 85 file.snapshotStruct.nodeCount = row.intValue; 86 break; 87 case 'edge_count': 88 file.snapshotStruct.edgeCount = row.intValue; 89 break; 90 case 'trace_function_count': 91 file.snapshotStruct.functionCount = row.intValue; 92 break; 93 } 94 } 95 } 96 97 private async loadNode(file: FileStruct) { 98 let result = await queryHeapNode(file.id); 99 let heapNodes = file.snapshotStruct.nodeMap; 100 let firstEdgeIndex = 0; 101 for (let row of result) { 102 let node = new HeapNode( 103 file.id, 104 row.nodeIndex, 105 row.type, 106 file.snapshotStruct.strings[row.nameIdx], 107 row.id, 108 row.selfSize, 109 row.edgeCount, 110 row.traceNodeId, 111 row.detachedness, 112 firstEdgeIndex 113 ); 114 if (file.snapshotStruct.rootNodeId === -1) { 115 file.snapshotStruct.rootNodeId = row.id; 116 } 117 heapNodes.set(node.id, node); 118 firstEdgeIndex += row.edgeCount; 119 } 120 } 121 122 private async loadEdge(file: FileStruct) { 123 file.snapshotStruct.edges = await queryHeapEdge(file.id); 124 } 125 126 private async loadTraceFunctionInfos(file: FileStruct) { 127 file.snapshotStruct.functionInfos = await queryHeapFunction(file.id); 128 } 129 130 private async loadTraceTree(file: FileStruct) { 131 let result = await queryHeapTraceNode(file.id); 132 let heapTraceNode = file.snapshotStruct.traceNodes; 133 let strings = file.snapshotStruct.strings; 134 for (let row of result) { 135 let traceNode = new AllocationFunction( 136 row.id, 137 strings[row.name], 138 strings[row.scriptName], 139 row.scriptId, 140 row.line, 141 row.column, 142 row.count, 143 row.size, 144 row.liveCount, 145 row.liveSize, 146 false 147 ); 148 traceNode.parentsId.push(row.parentId); 149 traceNode.functionIndex = row.functionInfoIndex; 150 traceNode.fileId = file.id; 151 heapTraceNode.push(traceNode); 152 } 153 } 154 155 private async loadSamples(file: FileStruct) { 156 file.snapshotStruct.samples = await queryHeapSample(file.id); 157 } 158 159 private async loadStrings(file: FileStruct) { 160 let result = await queryHeapString(file.id); 161 for (let data of result) { 162 file.snapshotStruct.strings.push(data.string); 163 } 164 } 165 166 async loadDatabase(listener: ParseListener) { 167 await this.loadFile(listener); 168 } 169} 170