1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ciimport { info } from '../../log/Log'; 16fb726d48Sopenharmony_ci 17fb726d48Sopenharmony_ci/** 18fb726d48Sopenharmony_ci * 数据缓存期限 19fb726d48Sopenharmony_ci */ 20fb726d48Sopenharmony_ciconst file_cache_due = 24 * 60 * 60 * 1000; 21fb726d48Sopenharmony_ciconst db_version = 6; 22fb726d48Sopenharmony_ci/** 23fb726d48Sopenharmony_ci * 初始化indexed db 24fb726d48Sopenharmony_ci */ 25fb726d48Sopenharmony_ciexport function initIndexedDB(): Promise<IDBDatabase> { 26fb726d48Sopenharmony_ci return new Promise((resolve, reject) => { 27fb726d48Sopenharmony_ci let request = indexedDB.open('smart_perf', db_version); 28fb726d48Sopenharmony_ci request.onerror = function (event): void {}; 29fb726d48Sopenharmony_ci request.onsuccess = function (event): void { 30fb726d48Sopenharmony_ci let db = request.result; 31fb726d48Sopenharmony_ci resolve(db); 32fb726d48Sopenharmony_ci }; 33fb726d48Sopenharmony_ci request.onupgradeneeded = function (event): void { 34fb726d48Sopenharmony_ci // @ts-ignore 35fb726d48Sopenharmony_ci let db = event!.target!.result; 36fb726d48Sopenharmony_ci if (db.objectStoreNames.contains('trace_file')) { 37fb726d48Sopenharmony_ci info('delete trace_file table'); 38fb726d48Sopenharmony_ci db.deleteObjectStore('trace_file'); 39fb726d48Sopenharmony_ci } 40fb726d48Sopenharmony_ci info('create trace_file table'); 41fb726d48Sopenharmony_ci let objectStore = db.createObjectStore('trace_file', { keyPath: 'file_index' }); 42fb726d48Sopenharmony_ci objectStore.createIndex('file_no', 'file_no'); 43fb726d48Sopenharmony_ci objectStore.createIndex('file_id', 'file_id'); 44fb726d48Sopenharmony_ci objectStore.createIndex('file_time', 'file_time'); 45fb726d48Sopenharmony_ci objectStore.createIndex('file_buffer', 'file_buffer'); 46fb726d48Sopenharmony_ci }; 47fb726d48Sopenharmony_ci }); 48fb726d48Sopenharmony_ci} 49fb726d48Sopenharmony_ci 50fb726d48Sopenharmony_ci/** 51fb726d48Sopenharmony_ci * 删除过期数据 52fb726d48Sopenharmony_ci * @param db 53fb726d48Sopenharmony_ci */ 54fb726d48Sopenharmony_ciexport function deleteExpireData(db: IDBDatabase): void { 55fb726d48Sopenharmony_ci if (db?.objectStoreNames.contains('trace_file')) { 56fb726d48Sopenharmony_ci let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file'); 57fb726d48Sopenharmony_ci let request = objectStore.getAll(); 58fb726d48Sopenharmony_ci request.onsuccess = function (event): void { 59fb726d48Sopenharmony_ci let now = new Date().getTime(); 60fb726d48Sopenharmony_ci for (let re of request.result) { 61fb726d48Sopenharmony_ci if (now - re.file_time > file_cache_due) { 62fb726d48Sopenharmony_ci objectStore.delete(re.file_index); 63fb726d48Sopenharmony_ci } 64fb726d48Sopenharmony_ci } 65fb726d48Sopenharmony_ci db.close(); 66fb726d48Sopenharmony_ci }; 67fb726d48Sopenharmony_ci request.onerror = function (): void { 68fb726d48Sopenharmony_ci info('delete expire data failed'); 69fb726d48Sopenharmony_ci }; 70fb726d48Sopenharmony_ci } 71fb726d48Sopenharmony_ci} 72fb726d48Sopenharmony_ci 73fb726d48Sopenharmony_ci/** 74fb726d48Sopenharmony_ci * 缓存数据 75fb726d48Sopenharmony_ci * @param db 数据库链接对象 76fb726d48Sopenharmony_ci * @param oldFileId 上次打开的文件id 77fb726d48Sopenharmony_ci * @param fileId 当前打开的文件id 78fb726d48Sopenharmony_ci * @param buffer 二进制数据 79fb726d48Sopenharmony_ci */ 80fb726d48Sopenharmony_ciexport function cacheTraceFileBuffer(db: IDBDatabase, oldFileId: string, fileId: string, buffer: ArrayBuffer): void { 81fb726d48Sopenharmony_ci if (db?.objectStoreNames.contains('trace_file')) { 82fb726d48Sopenharmony_ci let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file'); 83fb726d48Sopenharmony_ci let request = objectStore.index('file_id').getAll(oldFileId); 84fb726d48Sopenharmony_ci request.onsuccess = function (event): void { 85fb726d48Sopenharmony_ci for (let re of request.result) { 86fb726d48Sopenharmony_ci objectStore.delete(re.file_index); 87fb726d48Sopenharmony_ci } 88fb726d48Sopenharmony_ci info('delete file success'); 89fb726d48Sopenharmony_ci let size = buffer.byteLength; 90fb726d48Sopenharmony_ci let index = 0; 91fb726d48Sopenharmony_ci let no = 0; 92fb726d48Sopenharmony_ci let time = new Date().getTime(); 93fb726d48Sopenharmony_ci while (index < size) { 94fb726d48Sopenharmony_ci let sliceLen = Math.min(size - index, 4 * 1024 * 1024); 95fb726d48Sopenharmony_ci objectStore.add({ 96fb726d48Sopenharmony_ci file_index: randomUUID(), 97fb726d48Sopenharmony_ci file_no: no, 98fb726d48Sopenharmony_ci file_id: fileId, 99fb726d48Sopenharmony_ci file_time: time, 100fb726d48Sopenharmony_ci file_buffer: buffer.slice(index, index + sliceLen), 101fb726d48Sopenharmony_ci }); 102fb726d48Sopenharmony_ci no++; 103fb726d48Sopenharmony_ci index += sliceLen; 104fb726d48Sopenharmony_ci } 105fb726d48Sopenharmony_ci info('cache file success', fileId, buffer.byteLength); 106fb726d48Sopenharmony_ci db.close(); 107fb726d48Sopenharmony_ci }; 108fb726d48Sopenharmony_ci request.onerror = function (ev): void { 109fb726d48Sopenharmony_ci info('delete error', fileId); 110fb726d48Sopenharmony_ci }; 111fb726d48Sopenharmony_ci } 112fb726d48Sopenharmony_ci} 113fb726d48Sopenharmony_ci 114fb726d48Sopenharmony_cifunction randomUUID(): string { 115fb726d48Sopenharmony_ci // @ts-ignore 116fb726d48Sopenharmony_ci return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: unknown) => 117fb726d48Sopenharmony_ci //@ts-ignore 118fb726d48Sopenharmony_ci (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16) 119fb726d48Sopenharmony_ci ); 120fb726d48Sopenharmony_ci} 121fb726d48Sopenharmony_ci 122fb726d48Sopenharmony_ci/** 123fb726d48Sopenharmony_ci * 获取当前文件的 二进制数据 124fb726d48Sopenharmony_ci * @param fileId 125fb726d48Sopenharmony_ci */ 126fb726d48Sopenharmony_ciexport function getTraceFileBuffer(fileId: string): Promise<ArrayBuffer | null> { 127fb726d48Sopenharmony_ci return new Promise((resolve) => { 128fb726d48Sopenharmony_ci if (fileId === null || fileId === undefined || fileId === '') { 129fb726d48Sopenharmony_ci resolve(new Uint8Array(0).buffer); 130fb726d48Sopenharmony_ci } else { 131fb726d48Sopenharmony_ci initIndexedDB().then((db) => { 132fb726d48Sopenharmony_ci if (db?.objectStoreNames.contains('trace_file')) { 133fb726d48Sopenharmony_ci let request = db 134fb726d48Sopenharmony_ci .transaction(['trace_file'], 'readwrite') 135fb726d48Sopenharmony_ci .objectStore('trace_file') 136fb726d48Sopenharmony_ci .index('file_id') 137fb726d48Sopenharmony_ci .getAll(fileId); 138fb726d48Sopenharmony_ci request.onsuccess = function (ev): void { 139fb726d48Sopenharmony_ci let totalLen = 0; 140fb726d48Sopenharmony_ci let arr = request.result.sort((a, b) => a.file_no - b.file_no); 141fb726d48Sopenharmony_ci for (let re of arr) { 142fb726d48Sopenharmony_ci totalLen += re.file_buffer.byteLength; 143fb726d48Sopenharmony_ci } 144fb726d48Sopenharmony_ci let buffer = new Uint8Array(totalLen); 145fb726d48Sopenharmony_ci let offset = 0; 146fb726d48Sopenharmony_ci for (let re of arr) { 147fb726d48Sopenharmony_ci let ua = new Uint8Array(re.file_buffer); 148fb726d48Sopenharmony_ci buffer.set(ua, offset); 149fb726d48Sopenharmony_ci offset += re.file_buffer.byteLength; 150fb726d48Sopenharmony_ci } 151fb726d48Sopenharmony_ci arr.length = 0; 152fb726d48Sopenharmony_ci request.result.length = 0; 153fb726d48Sopenharmony_ci resolve(buffer.buffer); 154fb726d48Sopenharmony_ci }; 155fb726d48Sopenharmony_ci } else { 156fb726d48Sopenharmony_ci resolve(new Uint8Array(0).buffer); 157fb726d48Sopenharmony_ci } 158fb726d48Sopenharmony_ci }); 159fb726d48Sopenharmony_ci } 160fb726d48Sopenharmony_ci }); 161fb726d48Sopenharmony_ci} 162