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