• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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