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 for (let row of result) { 46 let fileStruct = new FileStruct(); 47 fileStruct.id = row.id; 48 fileStruct.name = row.name; 49 fileStruct.startTs = row.startTs; 50 fileStruct.endTs = row.endTs; 51 fileStruct.pid = row.pid; 52 fileStruct.size = row.size; 53 if (fileStruct.name.startsWith('Snapshot')) { 54 fileStruct.type = FileType.SNAPSHOT; 55 } else { 56 fileStruct.type = FileType.TIMELINE; 57 } 58 info(`read ${fileStruct.name} from db ${getTimeForLog()}`); 59 //fileStruct.profile.root_index = 0 60 await this.loadInfo(fileStruct); 61 await this.loadStrings(fileStruct); 62 await this.loadNode(fileStruct); 63 await this.loadEdge(fileStruct); 64 await this.loadTraceFunctionInfos(fileStruct); 65 await this.loadTraceTree(fileStruct); 66 await this.loadSamples(fileStruct); 67 info(`read ${fileStruct.name} from db Success ${getTimeForLog()}`); 68 this.fileModule.push(fileStruct); 69 } 70 let dataParse = HeapDataInterface.getInstance(); 71 dataParse.setPraseListener(listener); 72 dataParse.parseData(this.fileModule); 73 } 74 75 private async loadInfo(file: FileStruct) { 76 let result = await queryHeapInfo(file.id); 77 for (let row of result) { 78 if (row.key.includes('types')) continue; 79 switch (row.key) { 80 case 'node_count': 81 file.snapshotStruct.nodeCount = row.intValue; 82 break; 83 case 'edge_count': 84 file.snapshotStruct.edgeCount = row.intValue; 85 break; 86 case 'trace_function_count': 87 file.snapshotStruct.functionCount = row.intValue; 88 break; 89 } 90 } 91 } 92 93 private async loadNode(file: FileStruct) { 94 let result = await queryHeapNode(file.id); 95 let heapNodes = file.snapshotStruct.nodeMap; 96 let firstEdgeIndex = 0; 97 for (let row of result) { 98 let node = new HeapNode( 99 file.id, 100 row.nodeIndex, 101 row.type, 102 file.snapshotStruct.strings[row.nameIdx], 103 row.id, 104 row.selfSize, 105 row.edgeCount, 106 row.traceNodeId, 107 row.detachedness, 108 firstEdgeIndex 109 ); 110 if (file.snapshotStruct.rootNodeId === -1) { 111 file.snapshotStruct.rootNodeId = row.id; 112 } 113 heapNodes.set(node.id, node); 114 firstEdgeIndex += row.edgeCount; 115 } 116 } 117 118 private async loadEdge(file: FileStruct) { 119 file.snapshotStruct.edges = await queryHeapEdge(file.id); 120 } 121 122 private async loadTraceFunctionInfos(file: FileStruct) { 123 file.snapshotStruct.functionInfos = await queryHeapFunction(file.id); 124 } 125 126 private async loadTraceTree(file: FileStruct) { 127 let result = await queryHeapTraceNode(file.id); 128 let heapTraceNode = file.snapshotStruct.traceNodes; 129 let strings = file.snapshotStruct.strings; 130 for (let row of result) { 131 let traceNode = new AllocationFunction( 132 row.id, 133 strings[row.name], 134 strings[row.scriptName], 135 row.scriptId, 136 row.line, 137 row.column, 138 row.count, 139 row.size, 140 row.liveCount, 141 row.liveSize, 142 false 143 ); 144 traceNode.parentsId.push(row.parentId); 145 traceNode.functionIndex = row.functionInfoIndex; 146 traceNode.fileId = file.id; 147 heapTraceNode.push(traceNode); 148 } 149 } 150 151 private async loadSamples(file: FileStruct) { 152 file.snapshotStruct.samples = await queryHeapSample(file.id); 153 } 154 155 private async loadStrings(file: FileStruct) { 156 let result = await queryHeapString(file.id); 157 for (let data of result) { 158 file.snapshotStruct.strings.push(data.string); 159 } 160 } 161 162 async loadDatabase(listener: ParseListener) { 163 await this.loadFile(listener); 164 } 165} 166