* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { info } from '../../log/Log';
* 数据缓存期限
*/
const file_cache_due = 24 * 60 * 60 * 1000;
const db_version = 6;
* 初始化indexed db
*/
export function initIndexedDB(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
let request = indexedDB.open('smart_perf', db_version);
request.onerror = function (event): void {};
request.onsuccess = function (event): void {
let db = request.result;
resolve(db);
};
request.onupgradeneeded = function (event): void {
let db = event!.target!.result;
if (db.objectStoreNames.contains('trace_file')) {
info('delete trace_file table');
db.deleteObjectStore('trace_file');
}
info('create trace_file table');
let objectStore = db.createObjectStore('trace_file', { keyPath: 'file_index' });
objectStore.createIndex('file_no', 'file_no');
objectStore.createIndex('file_id', 'file_id');
objectStore.createIndex('file_time', 'file_time');
objectStore.createIndex('file_buffer', 'file_buffer');
};
});
}
* 删除过期数据
* @param db
*/
export function deleteExpireData(db: IDBDatabase): void {
if (db?.objectStoreNames.contains('trace_file')) {
let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
let request = objectStore.getAll();
request.onsuccess = function (event): void {
let now = new Date().getTime();
for (let re of request.result) {
if (now - re.file_time > file_cache_due) {
objectStore.delete(re.file_index);
}
}
db.close();
};
request.onerror = function (): void {
info('delete expire data failed');
};
}
}
* 缓存数据
* @param db 数据库链接对象
* @param oldFileId 上次打开的文件id
* @param fileId 当前打开的文件id
* @param buffer 二进制数据
*/
export function cacheTraceFileBuffer(db: IDBDatabase, oldFileId: string, fileId: string, buffer: ArrayBuffer): void {
if (db?.objectStoreNames.contains('trace_file')) {
let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
let request = objectStore.index('file_id').getAll(oldFileId);
request.onsuccess = function (event): void {
for (let re of request.result) {
objectStore.delete(re.file_index);
}
info('delete file success');
let size = buffer.byteLength;
let index = 0;
let no = 0;
let time = new Date().getTime();
while (index < size) {
let sliceLen = Math.min(size - index, 4 * 1024 * 1024);
objectStore.add({
file_index: randomUUID(),
file_no: no,
file_id: fileId,
file_time: time,
file_buffer: buffer.slice(index, index + sliceLen),
});
no++;
index += sliceLen;
}
info('cache file success', fileId, buffer.byteLength);
db.close();
};
request.onerror = function (ev): void {
info('delete error', fileId);
};
}
}
function randomUUID(): string {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: unknown) =>
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
);
}
* 获取当前文件的 二进制数据
* @param fileId
*/
export function getTraceFileBuffer(fileId: string): Promise<ArrayBuffer | null> {
return new Promise((resolve) => {
if (fileId === null || fileId === undefined || fileId === '') {
resolve(new Uint8Array(0).buffer);
} else {
initIndexedDB().then((db) => {
if (db?.objectStoreNames.contains('trace_file')) {
let request = db
.transaction(['trace_file'], 'readwrite')
.objectStore('trace_file')
.index('file_id')
.getAll(fileId);
request.onsuccess = function (ev): void {
let totalLen = 0;
let arr = request.result.sort((a, b) => a.file_no - b.file_no);
for (let re of arr) {
totalLen += re.file_buffer.byteLength;
}
let buffer = new Uint8Array(totalLen);
let offset = 0;
for (let re of arr) {
let ua = new Uint8Array(re.file_buffer);
buffer.set(ua, offset);
offset += re.file_buffer.byteLength;
}
arr.length = 0;
request.result.length = 0;
resolve(buffer.buffer);
};
} else {
resolve(new Uint8Array(0).buffer);
}
});
}
});
}