• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import { info } from '../../log/Log.js';
2
3/**
4 * 数据缓存期限
5 */
6const file_cache_due = 24 * 60 * 60 * 1000;
7const db_version = 6;
8/**
9 * 初始化indexed db
10 */
11export function initIndexedDB(): Promise<IDBDatabase> {
12  return new Promise((resolve, reject) => {
13    let request = indexedDB.open('smart_perf', db_version);
14    request.onerror = function (event) {};
15    request.onsuccess = function (event) {
16      let db = request.result;
17      resolve(db);
18    };
19    request.onupgradeneeded = function (event) {
20      // @ts-ignore
21      let db = event!.target!.result;
22      if (db.objectStoreNames.contains('trace_file')) {
23        info('delete trace_file table');
24        db.deleteObjectStore('trace_file');
25      }
26      info('create trace_file table');
27      let objectStore = db.createObjectStore('trace_file', { keyPath: 'file_index' });
28      objectStore.createIndex('file_no', 'file_no');
29      objectStore.createIndex('file_id', 'file_id');
30      objectStore.createIndex('file_time', 'file_time');
31      objectStore.createIndex('file_buffer', 'file_buffer');
32    };
33  });
34}
35
36/**
37 * 删除过期数据
38 * @param db
39 */
40export function deleteExpireData(db: IDBDatabase) {
41  if (db && db.objectStoreNames.contains('trace_file')) {
42    let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
43    let request = objectStore.getAll();
44    request.onsuccess = function (event) {
45      let now = new Date().getTime();
46      for (let re of request.result) {
47        if (now - re.file_time > file_cache_due) {
48          objectStore.delete(re.file_index);
49        }
50      }
51      db.close();
52    };
53    request.onerror = function () {
54      info('delete expire data failed');
55    };
56  }
57}
58
59/**
60 * 缓存数据
61 * @param db 数据库链接对象
62 * @param oldFileId 上次打开的文件id
63 * @param fileId 当前打开的文件id
64 * @param buffer 二进制数据
65 */
66export function cacheTraceFileBuffer(db: IDBDatabase, oldFileId: string, fileId: string, buffer: ArrayBuffer) {
67  if (db && db.objectStoreNames.contains('trace_file')) {
68    let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
69    let request = objectStore.index('file_id').getAll(oldFileId);
70    request.onsuccess = function (event) {
71      for (let re of request.result) {
72        objectStore.delete(re.file_index);
73      }
74      info('delete file success');
75      let size = buffer.byteLength;
76      let index = 0;
77      let no = 0;
78      let time = new Date().getTime();
79      while (index < size) {
80        let sliceLen = Math.min(size - index, 4 * 1024 * 1024);
81        objectStore.add({
82          file_index: randomUUID(),
83          file_no: no,
84          file_id: fileId,
85          file_time: time,
86          file_buffer: buffer.slice(index, index + sliceLen),
87        });
88        no++;
89        index += sliceLen;
90      }
91      info('cache file success', fileId, buffer.byteLength);
92      db.close();
93    };
94    request.onerror = function (ev) {
95      info('delete error', fileId);
96    };
97  }
98}
99
100function randomUUID(): string {
101  // @ts-ignore
102  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: any) =>
103    (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
104  );
105}
106
107/**
108 * 获取当前文件的 二进制数据
109 * @param fileId
110 */
111export function getTraceFileBuffer(fileId: string): Promise<ArrayBuffer | null> {
112  return new Promise((resolve) => {
113    if (fileId === null || fileId === undefined || fileId === '') {
114      resolve(new Uint8Array(0).buffer);
115    } else {
116      initIndexedDB().then((db) => {
117        if (db && db.objectStoreNames.contains('trace_file')) {
118          let request = db
119            .transaction(['trace_file'], 'readwrite')
120            .objectStore('trace_file')
121            .index('file_id')
122            .getAll(fileId);
123          request.onsuccess = function (ev) {
124            let totalLen = 0;
125            let arr = request.result.sort((a, b) => a.file_no - b.file_no);
126            for (let re of arr) {
127              totalLen += re.file_buffer.byteLength;
128            }
129            let buffer = new Uint8Array(totalLen);
130            let offset = 0;
131            for (let re of arr) {
132              let ua = new Uint8Array(re.file_buffer);
133              buffer.set(ua, offset);
134              offset += re.file_buffer.byteLength;
135            }
136            arr.length = 0;
137            request.result.length = 0;
138            resolve(buffer.buffer);
139          };
140        } else {
141          resolve(new Uint8Array(0).buffer);
142        }
143      });
144    }
145  });
146}