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}