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 */ 15 16importScripts('trace_streamer_builtin.js'); 17import { execProtoForWorker } from './data-trafic/utils/ExecProtoForWorker'; 18import { QueryEnum, TraficEnum } from './data-trafic/utils/QueryEnum'; 19// @ts-ignore 20import { temp_init_sql_list } from './TempSql'; 21// @ts-ignore 22import { BatchSphData } from '../proto/SphBaseData'; 23 24enum TsLogLevel { 25 DEBUG = 0, 26 INFO = 1, 27 WARN = 2, 28 ERROR = 3, 29 FATAL = 4, 30 OFF = 5, 31} 32 33let wasmModule: unknown = null; 34let enc = new TextEncoder(); 35let dec = new TextDecoder(); 36let arr: Uint8Array | undefined; 37const REQ_BUF_SIZE = 4 * 1024 * 1024; 38let reqBufferAddr: number = -1; 39let bufferSlice: Array<Uint8Array> = []; 40let headUnitArray: Uint8Array | undefined; 41let thirdWasmMap = new Map(); 42let thirdJsonResult = new Map(); 43 44const CONTENT_TYPE_CMDLINES = 2; 45const CONTENT_TYPE_TGIDS = 3; 46const CONTENT_TYPE_HEADER_PAGE = 30; 47const CONTENT_TYPE_PRINTK_FORMATS = 31; 48const CONTENT_TYPE_KALLSYMS = 32; 49 50let arkTsData: Array<Uint8Array> = []; 51let arkTsDataSize: number = 0; 52 53let currentAction: string = ''; 54let currentActionId: string = ''; 55let ffrtFileCacheKey = '-1'; 56let indexDB: IDBDatabase; 57const maxSize = 48 * 1024 * 1024; 58const currentTSLogLevel = TsLogLevel.OFF; 59//@ts-ignore 60let protoDataMap: Map<QueryEnum, BatchSphData> = new Map<QueryEnum, BatchSphData>(); 61function clear(): void { 62 if (wasmModule !== null) { 63 //@ts-ignore 64 wasmModule._TraceStreamerReset(); 65 wasmModule = null; 66 } 67 if (arr) { 68 arr = undefined; 69 } 70 if (headUnitArray) { 71 headUnitArray = undefined; 72 } 73 if (bufferSlice) { 74 bufferSlice.length = 0; 75 } 76 thirdWasmMap.clear(); 77 thirdJsonResult.clear(); 78} 79 80self.addEventListener('unhandledrejection', (err) => { 81 self.postMessage({ 82 id: currentActionId, 83 action: currentAction, 84 init: false, 85 status: false, 86 msg: err.reason.message, 87 }); 88}); 89 90function initWASM(): Promise<unknown> { 91 return new Promise((resolve, reject) => { 92 //@ts-ignore 93 let wasm = trace_streamer_builtin_wasm; 94 wasmModule = wasm({ 95 locateFile: (s: unknown) => { 96 return s; 97 }, 98 print: (line: string) => { 99 if (currentTSLogLevel < TsLogLevel.OFF) { 100 console.log(line); 101 } 102 }, 103 printErr: (line: string) => { 104 if (currentTSLogLevel < TsLogLevel.OFF) { 105 console.error(line); 106 } 107 }, 108 onRuntimeInitialized: () => { 109 resolve('ok'); 110 }, 111 onAbort: () => { 112 reject('on abort'); 113 }, 114 }); 115 }); 116} 117 118function initThirdWASM(wasmFunctionName: string): unknown { 119 function callModelFun(functionName: string): unknown { 120 let func = eval(functionName); 121 return new func({ 122 locateFile: (s: unknown): unknown => { 123 return s; 124 }, 125 print: (line: string): void => { 126 if (currentTSLogLevel < TsLogLevel.OFF) { 127 console.log(line); 128 } 129 }, 130 printErr: (line: string): void => { 131 if (currentTSLogLevel < TsLogLevel.OFF) { 132 console.error(line); 133 } 134 }, 135 onRuntimeInitialized: (): void => { }, 136 onAbort: (): void => { }, 137 }); 138 } 139 140 return callModelFun(wasmFunctionName); 141} 142 143let merged = (): Uint8Array => { 144 let length = 0; 145 bufferSlice.forEach((item) => { 146 //@ts-ignore 147 length += item.length; 148 }); 149 let mergedArray = new Uint8Array(length); 150 let offset = 0; 151 bufferSlice.forEach((item) => { 152 //@ts-ignore 153 mergedArray.set(item, offset); 154 //@ts-ignore 155 offset += item.length; 156 }); 157 return mergedArray; 158}; 159 160let translateJsonString = (str: string): string => { 161 return str // .padding 162 .replace(/[\t|\r|\n]/g, ''); 163}; 164 165let convertJSON = (): unknown[] => { 166 try { 167 let str = dec.decode(arr); 168 let jsonArray: Array<unknown> = []; 169 str = str.substring(str.indexOf('\n') + 1); 170 if (!str) { 171 } else { 172 let parse; 173 let tansStr: string; 174 try { 175 tansStr = str.replace(/[\t\r\n]/g, ''); 176 parse = JSON.parse(tansStr); 177 } catch { 178 try { 179 tansStr = tansStr!.replace(/[^\x20-\x7E]/g, '?'); //匹配乱码字 符,将其转换为? 180 parse = JSON.parse(tansStr); 181 } catch { 182 tansStr = tansStr!.replace(/\\/g, '\\\\'); 183 parse = JSON.parse(tansStr); 184 } 185 } 186 let columns = parse.columns; 187 let values = parse.values; 188 for (let i = 0; i < values.length; i++) { 189 let obj: unknown = {}; 190 for (let j = 0; j < columns.length; j++) { 191 //@ts-ignore 192 obj[columns[j]] = values[i][j]; 193 } 194 jsonArray.push(obj); 195 } 196 } 197 return jsonArray; 198 } catch (e) { 199 self.postMessage({ 200 id: currentActionId, 201 action: currentAction, 202 init: false, 203 status: false, 204 //@ts-ignore 205 msg: e.message, 206 }); 207 return []; 208 } 209}; 210 211/** 212 * 计算预留缓存空间,如果空间不够,则删除部分缓存 213 * @param size 214 */ 215function saveTraceFileBuffer(key: string, buffer: ArrayBuffer): void { 216 obligateFileBufferSpace(buffer.byteLength).then(() => { 217 caches.open(key).then((cache) => { 218 let headers = new Headers(); 219 headers.append('Content-Length', `${buffer.byteLength}`); 220 headers.append('Content-Type', 'application/octet-stream'); 221 cache 222 .put( 223 key, 224 new Response(buffer, { 225 status: 200, 226 headers: headers, 227 }) 228 ) 229 .then(); 230 }); 231 }); 232} 233 234async function obligateFileBufferSpace(size: number): Promise<void> { 235 let es = await navigator.storage.estimate(); 236 let remainderByte = (es.quota || 0) - (es.usage || 0) - 20 * 1024 * 1024; 237 if (remainderByte < size) { 238 let keys = await caches.keys(); 239 keys.sort((keyA, keyB) => { 240 if (keyA.includes('/') && keyB.includes('/')) { 241 let splitA = keyA.split('/'); 242 let splitB = keyB.split('/'); 243 let timeA = splitA[splitA.length - 1].split('-')[0]; 244 let timeB = splitB[splitB.length - 1].split('-')[0]; 245 return parseInt(timeA) - parseInt(timeB); 246 } else { 247 return 0; 248 } 249 }); 250 let needSize = size - remainderByte; 251 for (let key of keys) { 252 await caches.delete(key); 253 let keySize = parseInt(key.split('-')[1]); 254 if (keySize > needSize) { 255 return; 256 } else { 257 needSize -= keySize; 258 } 259 } 260 } 261} 262 263async function onmessageByOpenAction(e: MessageEvent): Promise<void> { 264 await initWASM(); 265 ffrtFileCacheKey = '-1'; 266 // @ts-ignore 267 self.postMessage({ 268 id: e.data.id, 269 action: e.data.action, 270 ready: true, 271 index: 0, 272 }); 273 let uint8Array = new Uint8Array(e.data.buffer); 274 initModuleCallBackAndFun(); 275 parseThirdWasmByOpenAction(e); 276 let wrSize = 0; 277 let r2 = -1; 278 if (isRawTrace(e.data)) { 279 r2 = parseRawTraceByOpenAction(e, wrSize, r2, uint8Array); 280 } else { 281 r2 = parseNormalTraceByOpenAction(wrSize, r2, uint8Array); 282 } 283 //@ts-ignore 284 wasmModule._TraceStreamerParseDataOver(); 285 for (let value of thirdWasmMap.values()) { 286 value.model._TraceStreamerInParseDataOver(); 287 } 288 postMessageByOpenAction(r2, e); 289} 290 291function initModuleCallBackAndFun(): void { 292 let callback = (heapPtr: number, size: number, isEnd: number): void => { 293 //@ts-ignore 294 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 295 bufferSlice.push(out); 296 if (isEnd === 1) { 297 arr = merged(); 298 bufferSlice.length = 0; 299 } 300 }; 301 let ffrtConvertCallback = (heapPtr: number, size: number, isEnd: number): void => { 302 if (isEnd !== 1) { 303 //@ts-ignore 304 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 305 bufferSlice.push(out); 306 } else { 307 arr = merged(); 308 bufferSlice.length = 0; 309 ffrtFileCacheKey = `ffrt/${new Date().getTime()}-${arr.buffer.byteLength}`; 310 // @ts-ignore 311 saveTraceFileBuffer(ffrtFileCacheKey, arr.buffer); 312 } 313 }; 314 let tlvResultCallback = (heapPtr: number, size: number, type: number, isEnd: number): void => { 315 //@ts-ignore 316 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 317 //@ts-ignore 318 protoDataMap.set(type, BatchSphData.decode(out).values); 319 }; 320 //@ts-ignore 321 let fn1 = wasmModule.addFunction(callback, 'viii'); 322 //@ts-ignore 323 let fn2 = wasmModule.addFunction(ffrtConvertCallback, 'viii'); 324 //@ts-ignore 325 let tlvResultFun = wasmModule.addFunction(tlvResultCallback, 'viiii'); 326 //@ts-ignore 327 wasmModule._TraceStreamerSetLogLevel(currentTSLogLevel); 328 //@ts-ignore 329 reqBufferAddr = wasmModule._Initialize(REQ_BUF_SIZE, fn1, tlvResultFun, fn2); 330} 331 332function parseThirdWasmByOpenAction(e: MessageEvent): void { 333 let parseConfig = e.data.parseConfig; 334 if (parseConfig !== '') { 335 let parseConfigArray = enc.encode(parseConfig); 336 //@ts-ignore 337 let parseConfigAddr = wasmModule._InitializeParseConfig(parseConfigArray.length); 338 //@ts-ignore 339 wasmModule.HEAPU8.set(parseConfigArray, parseConfigAddr); 340 //@ts-ignore 341 wasmModule._TraceStreamerParserConfigEx(parseConfigArray.length); 342 } 343 let wasmConfigStr = e.data.wasmConfig; 344 if (wasmConfigStr !== '' && wasmConfigStr.indexOf('WasmFiles') !== -1) { 345 let wasmConfig = JSON.parse(wasmConfigStr); 346 let wasmConfigs = wasmConfig.WasmFiles; 347 let itemArray = wasmConfigs.map((item: unknown) => { 348 //@ts-ignore 349 return item.componentId + ';' + item.pluginName; 350 }); 351 let thirdWasmStr: string = itemArray.join(';'); 352 let configUintArray = enc.encode(thirdWasmStr + ';'); 353 //@ts-ignore 354 wasmModule.HEAPU8.set(configUintArray, reqBufferAddr); 355 //@ts-ignore 356 wasmModule._TraceStreamerInitThirdPartyConfig(configUintArray.length); 357 let first = true; 358 let sendDataCallback = (heapPtr: number, size: number, componentID: number): void => { 359 if (componentID === 100) { 360 if (first) { 361 first = false; 362 //@ts-ignore 363 headUnitArray = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 364 } 365 return; 366 } 367 let configs = wasmConfigs.filter((wasmConfig: unknown) => { 368 //@ts-ignore 369 return wasmConfig.componentId === componentID; 370 }); 371 if (configs.length > 0) { 372 let config = configs[0]; 373 let model = thirdWasmMap.get(componentID); 374 if (!model && config.componentId === componentID) { 375 importScripts(config.wasmJsName); 376 setThirdWasmMap(config, heapPtr, size, componentID); 377 } else { 378 let mm = model.model; 379 //@ts-ignore 380 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 381 mm.HEAPU8.set(out, model.bufferAddr); 382 mm._ParserData(out.length, componentID); 383 } 384 } 385 }; 386 //@ts-ignore 387 let fn1 = wasmModule.addFunction(sendDataCallback, 'viii'); 388 //@ts-ignore 389 wasmModule._TraceStreamerSetThirdPartyDataDealer(fn1, REQ_BUF_SIZE); 390 } 391} 392 393function isCommonData(dataType: number): boolean { 394 return ( 395 dataType === CONTENT_TYPE_CMDLINES || 396 dataType === CONTENT_TYPE_TGIDS || 397 dataType === CONTENT_TYPE_HEADER_PAGE || 398 dataType === CONTENT_TYPE_PRINTK_FORMATS || 399 dataType === CONTENT_TYPE_KALLSYMS 400 ); 401} 402 403function parseRawTraceByOpenAction(e: MessageEvent, wrSize: number, r2: number, uint8Array: Uint8Array): number { 404 let commonDataOffsetList: Array<{ startOffset: number; endOffset: number }> = []; // common Data 405 let offset = 12; 406 let tlvTypeLength = 4; 407 let headArray = uint8Array.slice(0, offset); 408 let commonTotalLength = 0; 409 while (offset < uint8Array.length) { 410 let commonDataOffset = { startOffset: offset, endOffset: offset }; 411 let dataTypeData = e.data.buffer.slice(offset, offset + tlvTypeLength); 412 offset += tlvTypeLength; 413 let dataType = Array.from(new Uint32Array(dataTypeData)); 414 let currentLData = e.data.buffer.slice(offset, offset + tlvTypeLength); 415 offset += tlvTypeLength; 416 let currentVLength = Array.from(new Uint32Array(currentLData)); 417 offset += currentVLength[0]; 418 commonDataOffset.endOffset = offset; 419 if (isCommonData(dataType[0])) { 420 commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; 421 commonDataOffsetList.push(commonDataOffset); 422 } 423 } 424 let frontData = new Uint8Array(headArray.byteLength + commonTotalLength); // HeadArray 425 frontData.set(headArray, 0); 426 let lengthOffset = headArray.byteLength; 427 commonDataOffsetList.forEach((item) => { 428 let commonData = uint8Array.slice(item.startOffset, item.endOffset); 429 frontData.set(commonData, lengthOffset); 430 lengthOffset += commonData.byteLength; 431 }); 432 let freeData = uint8Array.slice(12); 433 let final = new Uint8Array(frontData.length + freeData.length); 434 final.set(frontData); 435 final.set(freeData, frontData.length); 436 wrSize = 0; 437 while (wrSize < final.length) { 438 const sliceLen = Math.min(final.length - wrSize, REQ_BUF_SIZE); 439 const dataSlice = final.subarray(wrSize, wrSize + sliceLen); 440 //@ts-ignore 441 wasmModule.HEAPU8.set(dataSlice, reqBufferAddr); 442 wrSize += sliceLen; 443 //@ts-ignore 444 r2 = wasmModule._TraceStreamerParseDataEx(sliceLen, wrSize === final.length ? 1 : 0); 445 if (r2 === -1) { 446 break; 447 } 448 } 449 return r2; 450} 451 452function parseNormalTraceByOpenAction(wrSize: number, r2: number, uint8Array: Uint8Array): number { 453 while (wrSize < uint8Array.length) { 454 const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE); 455 const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen); 456 //@ts-ignore 457 wasmModule.HEAPU8.set(dataSlice, reqBufferAddr); 458 wrSize += sliceLen; 459 //@ts-ignore 460 r2 = wasmModule._TraceStreamerParseDataEx(sliceLen, wrSize === uint8Array.length ? 1 : 0); 461 if (r2 === -1) { 462 break; 463 } 464 } 465 return r2; 466} 467 468function setThirdWasmMap(config: unknown, heapPtr: number, size: number, componentID: number): void { 469 //@ts-ignore 470 let thirdMode = initThirdWASM(config.wasmName); 471 //@ts-ignore 472 let configPluginName = config.pluginName; 473 let pluginNameUintArray = enc.encode(configPluginName); 474 //@ts-ignore 475 let pluginNameBuffer = thirdMode._InitPluginName(pluginNameUintArray.length); 476 //@ts-ignore 477 thirdMode.HEAPU8.set(pluginNameUintArray, pluginNameBuffer); 478 //@ts-ignore 479 thirdMode._TraceStreamerGetPluginNameEx(configPluginName.length); 480 let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number): void => { 481 if (isConfig === 1) { 482 //@ts-ignore 483 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 484 thirdJsonResult.set(componentID, { 485 jsonConfig: dec.decode(out), 486 //@ts-ignore 487 disPlayName: config.disPlayName, 488 //@ts-ignore 489 pluginName: config.pluginName, 490 }); 491 } else { 492 //@ts-ignore 493 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 494 bufferSlice.push(out); 495 if (isEnd === 1) { 496 arr = merged(); 497 bufferSlice.length = 0; 498 } 499 } 500 }; 501 //@ts-ignore 502 let fn = thirdMode.addFunction(thirdQueryDataCallBack, 'viiii'); 503 //@ts-ignore 504 let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE); 505 initTraceRange(thirdMode); 506 //@ts-ignore 507 thirdMode._TraceStreamerInJsonConfig(); 508 //@ts-ignore 509 thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr); 510 //@ts-ignore 511 thirdMode._ParserData(headUnitArray!.length, 100); 512 //@ts-ignore 513 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 514 //@ts-ignore 515 thirdMode.HEAPU8.set(out, thirdreqBufferAddr); 516 //@ts-ignore 517 thirdMode._ParserData(out.length, componentID); 518 thirdWasmMap.set(componentID, { 519 model: thirdMode, 520 bufferAddr: thirdreqBufferAddr, 521 }); 522} 523 524function postMessageByOpenAction(r2: number, e: MessageEvent): void { 525 if (r2 === -1) { 526 // @ts-ignore 527 self.postMessage({ 528 id: e.data.id, 529 action: e.data.action, 530 init: false, 531 msg: 'parse data error', 532 }); 533 return; 534 } 535 // @ts-ignore 536 if (temp_init_sql_list && temp_init_sql_list.length > 0) { 537 // @ts-ignore 538 temp_init_sql_list.forEach((item, index) => { 539 createView(item); 540 // @ts-ignore 541 self.postMessage({ id: e.data.id, ready: true, index: index + 1 }); 542 }); 543 } 544 545 self.postMessage( 546 { 547 id: e.data.id, 548 action: e.data.action, 549 init: true, 550 msg: 'ok', 551 configSqlMap: thirdJsonResult, 552 buffer: e.data.buffer, 553 fileKey: ffrtFileCacheKey, 554 }, 555 // @ts-ignore 556 [e.data.buffer] 557 ); 558} 559 560function initTraceRange(thirdMode: unknown): void { 561 let updateTraceTimeCallBack = (heapPtr: number, size: number): void => { 562 //@ts-ignore 563 let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); 564 //@ts-ignore 565 wasmModule.HEAPU8.set(out, reqBufferAddr); 566 //@ts-ignore 567 wasmModule._UpdateTraceTime(out.length); 568 }; 569 //@ts-ignore 570 let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, 'vii'); 571 //@ts-ignore 572 thirdMode._InitTraceRange(traceRangeFn, 1024); 573} 574 575function onmessageByExecAction(e: MessageEvent): void { 576 query(e.data.name, e.data.sql, e.data.params); 577 let jsonArray = convertJSON(); 578 // @ts-ignore 579 self.postMessage({ 580 id: e.data.id, 581 action: e.data.action, 582 results: jsonArray, 583 }); 584} 585 586function onmessageByExecProtoAction(e: MessageEvent): void { 587 let typeLength = 4; 588 execProtoForWorker(e.data, (sql: string) => { 589 let sqlUintArray = enc.encode(sql); 590 if (e.data.params.trafic !== TraficEnum.ProtoBuffer) { 591 //@ts-ignore 592 wasmModule.HEAPU8.set(sqlUintArray, reqBufferAddr); 593 //@ts-ignore 594 wasmModule._TraceStreamerSqlQueryEx(sqlUintArray.length); 595 let jsonArray = convertJSON(); 596 return jsonArray; 597 } else { 598 let allArray = new Uint8Array(typeLength + sqlUintArray.length); 599 allArray[0] = e.data.name; 600 allArray.set(sqlUintArray, typeLength); 601 //@ts-ignore 602 wasmModule.HEAPU8.set(allArray, reqBufferAddr); 603 //@ts-ignore 604 wasmModule._TraceStreamerSqlQueryToProtoCallback(allArray.length); 605 let finalArrayBuffer = []; 606 if (protoDataMap.has(e.data.name)) { 607 //@ts-ignore 608 finalArrayBuffer = protoDataMap.get(e.data.name); 609 protoDataMap.delete(e.data.name); 610 } 611 return finalArrayBuffer; 612 } 613 }); 614} 615 616function onmessageByExecBufAction(e: MessageEvent): void { 617 query(e.data.name, e.data.sql, e.data.params); 618 self.postMessage( 619 { id: e.data.id, action: e.data.action, results: arr!.buffer }, 620 // @ts-ignore 621 [arr.buffer] 622 ); 623} 624 625function onmessageByExecSdkAction(e: MessageEvent): void { 626 querySdk(e.data.name, e.data.sql, e.data.params, e.data.action); 627 let jsonArray = convertJSON(); 628 // @ts-ignore 629 self.postMessage({ 630 id: e.data.id, 631 action: e.data.action, 632 results: jsonArray, 633 }); 634} 635 636function onmessageByExecMetricAction(e: MessageEvent): void { 637 queryMetric(e.data.sql); 638 let metricResult = dec.decode(arr); 639 // @ts-ignore 640 self.postMessage({ 641 id: e.data.id, 642 action: e.data.action, 643 results: metricResult, 644 }); 645} 646 647function onmessageByInitPortAction(e: MessageEvent): void { 648 let port = e.ports[0]; 649 port.onmessage = (me): void => { 650 query(me.data.action, me.data.sql, me.data.params); 651 let msg = { 652 id: me.data.id, 653 action: me.data.action, 654 results: arr!.buffer, 655 }; 656 port.postMessage(msg, [arr!.buffer]); 657 }; 658} 659 660function onmessageByDownloadDBAction(e: MessageEvent): void { 661 let bufferSliceUint: Array<Uint8Array> = []; 662 let mergedUint = (): Uint8Array => { 663 let length = 0; 664 bufferSliceUint.forEach((item) => { 665 length += item.length; 666 }); 667 let mergedArray = new Uint8Array(length); 668 let offset = 0; 669 bufferSliceUint.forEach((item) => { 670 mergedArray.set(item, offset); 671 offset += item.length; 672 }); 673 return mergedArray; 674 }; 675 let getDownloadDb = (heapPtr: number, size: number, isEnd: number): void => { 676 //@ts-ignore 677 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 678 bufferSliceUint.push(out); 679 if (isEnd === 1) { 680 let arr: Uint8Array = mergedUint(); 681 self.postMessage({ 682 id: e.data.id, 683 action: e.data.action, 684 results: arr, 685 }); 686 } 687 }; 688 //@ts-ignore 689 let fn1 = wasmModule.addFunction(getDownloadDb, 'viii'); 690 //@ts-ignore 691 wasmModule._WasmExportDatabase(fn1); 692} 693 694function onmessageByUploadSoAction(e: MessageEvent): void { 695 uploadSoActionId = e.data.id; 696 const fileList = e.data.params as Array<File>; 697 failedArray.length = 0; 698 if (fileList) { 699 fileList.sort((a, b) => b.size - a.size); 700 soFileList = fileList; 701 uploadFileIndex = 0; 702 if (!uploadSoCallbackFn) { 703 //@ts-ignore 704 uploadSoCallbackFn = wasmModule.addFunction(uploadSoCallBack, 'viii'); 705 } 706 uploadSoFile(soFileList[uploadFileIndex]).then(); 707 } 708} 709 710async function saveDataToIndexDB( 711 currentChunk: Uint8Array, 712 currentChunkOffset: number, 713 fileType: string, 714 timStamp: number, 715 pageNum: number, 716 saveIndex: number, 717 saveStartOffset: number 718): Promise<void> { 719 let freeArray = currentChunk.slice(0, currentChunkOffset); 720 await addDataToIndexeddb(indexDB, { 721 buf: freeArray, 722 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 723 fileType: `${fileType}_new`, 724 pageNum: pageNum, 725 startOffset: saveStartOffset, 726 endOffset: saveStartOffset + maxSize, 727 index: saveIndex, 728 timStamp: timStamp, 729 }); 730} 731 732function cutLongTraceCallBackHandle( 733 traceFileType: string, 734 currentPageNum: number, 735 heapPtr: number, 736 size: number, 737 dataType: number, 738 newCutFilePageInfo: Map< 739 string, 740 { 741 traceFileType: string; 742 dataArray: [{ data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }]; 743 } 744 > 745): void { 746 let key = `${traceFileType}_${currentPageNum}`; 747 //@ts-ignore 748 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 749 if (DataTypeEnum.data === dataType) { 750 if (traceFileType === 'arkts') { 751 arkTsData.push(out); 752 arkTsDataSize += size; 753 } else { 754 if (newCutFilePageInfo.has(key)) { 755 let newVar = newCutFilePageInfo.get(key); 756 newVar?.dataArray.push({ data: out, dataTypes: 'data' }); 757 } else { 758 newCutFilePageInfo.set(key, { 759 traceFileType: traceFileType, 760 dataArray: [{ data: out, dataTypes: 'data' }], 761 }); 762 } 763 } 764 } else if (DataTypeEnum.json === dataType) { 765 let cutFilePageInfo = newCutFilePageInfo.get(key); 766 if (cutFilePageInfo) { 767 let jsonStr: string = dec.decode(out); 768 let jsonObj = JSON.parse(jsonStr); 769 let valueArray: Array<{ offset: number; size: number }> = jsonObj.value; 770 cutFilePageInfo.dataArray.push({ data: valueArray, dataTypes: 'json' }); 771 } 772 } 773} 774 775function initSplitLongTraceModuleAndFun( 776 headArray: Uint8Array, 777 cutFileCallBack: (heapPtr: number, size: number, dataType: number, isEnd: number) => void 778): number { 779 //@ts-ignore 780 splitReqBufferAddr = wasmModule._InitializeSplitFile(wasmModule.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); 781 //@ts-ignore 782 wasmModule.HEAPU8.set(headArray, splitReqBufferAddr); 783 //@ts-ignore 784 wasmModule._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); 785 return splitReqBufferAddr; 786} 787 788async function handleDataTypeBySplitLongTrace( 789 receiveData: { data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }, 790 currentChunkOffset: number, 791 currentChunk: Uint8Array, 792 fileType: string, 793 timStamp: number, 794 pageNum: number, 795 saveIndex: number, 796 saveStartOffset: number 797): Promise<[number, number, number, Uint8Array]> { 798 let receiveDataArray = receiveData.data as Uint8Array; 799 if (currentChunkOffset + receiveDataArray.length > maxSize) { 800 let freeSize = maxSize - currentChunkOffset; 801 let freeSaveData = receiveDataArray.slice(0, freeSize); 802 currentChunk.set(freeSaveData, currentChunkOffset); 803 await addDataToIndexeddb(indexDB, { 804 buf: currentChunk, 805 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 806 fileType: `${fileType}_new`, 807 pageNum: pageNum, 808 startOffset: saveStartOffset, 809 endOffset: saveStartOffset + maxSize, 810 index: saveIndex, 811 timStamp: timStamp, 812 }); 813 saveStartOffset += maxSize; 814 saveIndex++; 815 currentChunk = new Uint8Array(maxSize); 816 let remnantArray = receiveDataArray.slice(freeSize); 817 currentChunkOffset = 0; 818 currentChunk.set(remnantArray, currentChunkOffset); 819 currentChunkOffset += remnantArray.length; 820 } else { 821 currentChunk.set(receiveDataArray, currentChunkOffset); 822 currentChunkOffset += receiveDataArray.length; 823 } 824 return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; 825} 826 827async function saveAllDataByLongTrace( 828 range: IDBKeyRange, 829 nowCutInfoList: Array<unknown>, 830 searchDataInfo: { 831 fileType: string; 832 index: number; 833 pageNum: number; 834 startOffsetSize: number; 835 endOffsetSize: number; 836 }[], 837 currentChunkOffset: number, 838 currentChunk: Uint8Array, 839 fileType: string, 840 timStamp: number, 841 pageNum: number, 842 saveIndex: number, 843 saveStartOffset: number 844): Promise<[number, number, number, Uint8Array]> { 845 let transaction = indexDB.transaction(STORE_NAME, 'readonly'); 846 let store = transaction.objectStore(STORE_NAME); 847 let index = store.index('QueryCompleteFile'); 848 const getRequest = index.openCursor(range); 849 let queryAllData = await queryDataFromIndexeddb(getRequest); 850 let mergeData = indexedDataToBufferData(queryAllData); 851 for (let cutOffsetObjIndex = 0; cutOffsetObjIndex < nowCutInfoList.length; cutOffsetObjIndex++) { 852 let cutUseOffsetObj = nowCutInfoList[cutOffsetObjIndex]; 853 //@ts-ignore 854 let endOffset = cutUseOffsetObj.offset + cutUseOffsetObj.size; 855 let sliceData = mergeData.slice( 856 //@ts-ignore 857 cutUseOffsetObj.offset - searchDataInfo[0].startOffsetSize, 858 endOffset - searchDataInfo[0].startOffsetSize 859 ); 860 let sliceDataLength = sliceData.length; 861 if (currentChunkOffset + sliceDataLength >= maxSize) { 862 let handleCurrentData = new Uint8Array(currentChunkOffset + sliceDataLength); 863 let freeSaveArray = currentChunk.slice(0, currentChunkOffset); 864 handleCurrentData.set(freeSaveArray, 0); 865 handleCurrentData.set(sliceData, freeSaveArray.length); 866 let newSliceDataLength: number = Math.ceil(handleCurrentData.length / maxSize); 867 for (let newSliceIndex = 0; newSliceIndex < newSliceDataLength; newSliceIndex++) { 868 let newSliceSize = newSliceIndex * maxSize; 869 let number = Math.min(newSliceSize + maxSize, handleCurrentData.length); 870 let saveArray = handleCurrentData.slice(newSliceSize, number); 871 if (newSliceIndex === newSliceDataLength - 1 && number - newSliceSize < maxSize) { 872 currentChunk = new Uint8Array(maxSize); 873 currentChunkOffset = 0; 874 currentChunk.set(saveArray, currentChunkOffset); 875 currentChunkOffset += saveArray.length; 876 } else { 877 await addDataToIndexeddb(indexDB, { 878 buf: saveArray, 879 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 880 fileType: `${fileType}_new`, 881 pageNum: pageNum, 882 startOffset: saveStartOffset, 883 endOffset: saveStartOffset + maxSize, 884 index: saveIndex, 885 timStamp: timStamp, 886 }); 887 saveStartOffset += maxSize; 888 saveIndex++; 889 } 890 } 891 } else { 892 currentChunk.set(sliceData, currentChunkOffset); 893 currentChunkOffset += sliceDataLength; 894 } 895 } 896 return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; 897} 898 899async function handleJsonTypeBySplitLongTrace( 900 receiveData: { data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }, 901 allIndexDataList: Array<{ 902 fileType: string; 903 index: number; 904 pageNum: number; 905 startOffsetSize: number; 906 endOffsetSize: number; 907 }>, 908 fileType: string, 909 timStamp: number, 910 currentChunkOffset: number, 911 currentChunk: Uint8Array, 912 pageNum: number, 913 saveIndex: number, 914 saveStartOffset: number 915): Promise<[number, number, number, Uint8Array]> { 916 let needCutMessage = receiveData.data as Array<{ offset: number; size: number }>; 917 let startOffset = needCutMessage[0].offset; 918 let nowCutInfoList: Array<{ 919 offset: number; 920 size: number; 921 }> = []; 922 let isBeforeCutFinish = false; 923 for (let needCutIndex = 0; needCutIndex < needCutMessage.length; needCutIndex++) { 924 let cutInfo = needCutMessage[needCutIndex]; 925 if (isBeforeCutFinish) { 926 startOffset = cutInfo.offset; 927 isBeforeCutFinish = false; 928 nowCutInfoList.length = 0; 929 } 930 if (cutInfo.offset + cutInfo.size - startOffset >= maxSize * 10 || needCutIndex === needCutMessage.length - 1) { 931 nowCutInfoList.push(cutInfo); 932 //@ts-ignore 933 let nowStartCutOffset = nowCutInfoList[0].offset; 934 let nowEndCutOffset = cutInfo.offset + cutInfo.size; 935 let searchDataInfo = allIndexDataList.filter( 936 (value: { 937 fileType: string; 938 index: number; 939 pageNum: number; 940 startOffsetSize: number; 941 endOffsetSize: number; 942 }) => { 943 return ( 944 value.fileType === fileType && 945 value.startOffsetSize <= nowEndCutOffset && 946 value.endOffsetSize >= nowStartCutOffset 947 ); 948 } 949 ); 950 let startIndex = searchDataInfo[0].index; 951 let endIndex = searchDataInfo[searchDataInfo.length - 1].index; 952 let range = IDBKeyRange.bound( 953 [timStamp, fileType, 0, startIndex], 954 [timStamp, fileType, 0, endIndex], 955 false, 956 false 957 ); 958 [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = await saveAllDataByLongTrace( 959 range, 960 nowCutInfoList, 961 searchDataInfo, 962 currentChunkOffset, 963 currentChunk, 964 fileType, 965 timStamp, 966 pageNum, 967 saveIndex, 968 saveStartOffset 969 ); 970 isBeforeCutFinish = true; 971 } else { 972 nowCutInfoList.push(cutInfo); 973 } 974 } 975 return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; 976} 977 978async function handleAllTypeDataByLongTrace( 979 newCutFilePageInfo: Map< 980 string, 981 { 982 traceFileType: string; 983 dataArray: [ 984 { 985 data: Uint8Array | Array<{ offset: number; size: number }>; 986 dataTypes: string; 987 } 988 ]; 989 } 990 >, 991 timStamp: number, 992 allIndexDataList: Array<{ 993 fileType: string; 994 index: number; 995 pageNum: number; 996 startOffsetSize: number; 997 endOffsetSize: number; 998 }> 999): Promise<void> { 1000 for (const [fileTypePageNum, fileMessage] of newCutFilePageInfo) { 1001 let fileTypePageNumArr = fileTypePageNum.split('_'); 1002 let fileType = fileTypePageNumArr[0]; 1003 let pageNum = Number(fileTypePageNumArr[1]); 1004 let saveIndex = 0; 1005 let saveStartOffset = 0; 1006 let dataArray = fileMessage.dataArray; 1007 let currentChunk = new Uint8Array(maxSize); 1008 let currentChunkOffset = 0; 1009 for (let fileDataIndex = 0; fileDataIndex < dataArray.length; fileDataIndex++) { 1010 let receiveData = dataArray[fileDataIndex]; 1011 if (receiveData.dataTypes === 'data') { 1012 // @ts-ignore 1013 [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = await handleDataTypeBySplitLongTrace( 1014 receiveData, 1015 currentChunkOffset, 1016 currentChunk, 1017 fileType, 1018 timStamp, 1019 pageNum, 1020 saveIndex, 1021 saveStartOffset 1022 ); 1023 } else { 1024 if (receiveData.data.length > 0) { 1025 // @ts-ignore 1026 [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = await handleJsonTypeBySplitLongTrace( 1027 receiveData, 1028 allIndexDataList, 1029 fileType, 1030 timStamp, 1031 currentChunkOffset, 1032 currentChunk, 1033 pageNum, 1034 saveIndex, 1035 saveStartOffset 1036 ); 1037 } 1038 } 1039 } 1040 if (currentChunkOffset !== 0) { 1041 await saveDataToIndexDB( 1042 currentChunk, 1043 currentChunkOffset, 1044 fileType, 1045 timStamp, 1046 pageNum, 1047 saveIndex, 1048 saveStartOffset 1049 ); 1050 saveStartOffset += maxSize; 1051 saveIndex++; 1052 } 1053 } 1054} 1055 1056async function onmessageByLongTraceAction(e: MessageEvent): Promise<void> { 1057 await initWASM(); 1058 let result = {}; 1059 let headArray = e.data.params.headArray; 1060 let timStamp = e.data.params.timeStamp; 1061 let allIndexDataList = e.data.params.splitDataList; 1062 let splitFileInfos = e.data.params.splitFileInfo as Array<{ 1063 fileType: string; 1064 startIndex: number; 1065 endIndex: number; 1066 size: number; 1067 }>; 1068 let maxPageNum = headArray.length / 1024; 1069 let currentPageNum = 0; 1070 let splitReqBufferAddr: number; 1071 if (splitFileInfos) { 1072 let splitFileInfo = splitFileInfos.filter((splitFileInfo) => splitFileInfo.fileType !== 'trace'); 1073 if (splitFileInfo && splitFileInfo.length > 0) { 1074 let traceFileType: string = ''; 1075 indexDB = await openDB(); 1076 let newCutFilePageInfo: Map< 1077 string, 1078 { 1079 traceFileType: string; 1080 dataArray: [{ data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }]; 1081 } 1082 > = new Map(); 1083 let cutFileCallBack = (heapPtr: number, size: number, dataType: number, isEnd: number): void => { 1084 cutLongTraceCallBackHandle(traceFileType, currentPageNum, heapPtr, size, dataType, newCutFilePageInfo); 1085 }; 1086 splitReqBufferAddr = initSplitLongTraceModuleAndFun(headArray, cutFileCallBack); 1087 for (let fileIndex = 0; fileIndex < splitFileInfo.length; fileIndex++) { 1088 let fileInfo = splitFileInfo[fileIndex]; 1089 traceFileType = fileInfo.fileType; 1090 for (let pageNum = 0; pageNum < maxPageNum; pageNum++) { 1091 currentPageNum = pageNum; 1092 await splitFileAndSave(timStamp, fileInfo, pageNum, splitReqBufferAddr); 1093 await initWASM(); 1094 splitReqBufferAddr = initSplitLongTraceModuleAndFun(headArray, cutFileCallBack); 1095 } 1096 } 1097 await handleAllTypeDataByLongTrace(newCutFilePageInfo, timStamp, allIndexDataList); 1098 } 1099 } 1100 self.postMessage({ 1101 id: e.data.id, 1102 action: e.data.action, 1103 results: result, 1104 }); 1105 return; 1106} 1107 1108self.onmessage = async (e: MessageEvent): Promise<void> => { 1109 currentAction = e.data.action; 1110 currentActionId = e.data.id; 1111 if (e.data.action === 'reset') { 1112 clear(); 1113 } else if (e.data.action === 'open') { 1114 await onmessageByOpenAction(e); 1115 } else if (e.data.action === 'exec') { 1116 onmessageByExecAction(e); 1117 } else if (e.data.action === 'exec-proto') { 1118 onmessageByExecProtoAction(e); 1119 } else if (e.data.action === 'exec-buf') { 1120 onmessageByExecBufAction(e); 1121 } else if (e.data.action.startsWith('exec-sdk')) { 1122 onmessageByExecSdkAction(e); 1123 } else if (e.data.action.startsWith('exec-metric')) { 1124 onmessageByExecMetricAction(e); 1125 } else if (e.data.action === 'init-port') { 1126 onmessageByInitPortAction(e); 1127 } else if (e.data.action === 'download-db') { 1128 onmessageByDownloadDBAction(e); 1129 } else if (e.data.action === 'upload-so') { 1130 onmessageByUploadSoAction(e); 1131 } else if (e.data.action === 'cut-file') { 1132 cutFileByRange(e); 1133 } else if (e.data.action === 'long_trace') { 1134 await onmessageByLongTraceAction(e); 1135 } 1136}; 1137 1138function indexedDataToBufferData(sourceData: unknown): Uint8Array { 1139 let uintArrayLength = 0; 1140 //@ts-ignore 1141 let uintDataList = sourceData.map((item: unknown) => { 1142 //@ts-ignore 1143 let currentBufData = new Uint8Array(item.buf); 1144 uintArrayLength += currentBufData.length; 1145 return currentBufData; 1146 }); 1147 let resultUintArray = new Uint8Array(uintArrayLength); 1148 let offset = 0; 1149 uintDataList.forEach((currentArray: Uint8Array) => { 1150 resultUintArray.set(currentArray, offset); 1151 offset += currentArray.length; 1152 }); 1153 return resultUintArray; 1154} 1155 1156async function splitFileAndSaveArkTs( 1157 currentChunkOffset: number, 1158 currentChunk: Uint8Array, 1159 fileType: string, 1160 pageNum: number, 1161 saveStartOffset: number, 1162 saveIndex: number, 1163 timStamp: number 1164): Promise<void> { 1165 for (let arkTsAllDataIndex = 0; arkTsAllDataIndex < arkTsData.length; arkTsAllDataIndex++) { 1166 let currentArkTsData = arkTsData[arkTsAllDataIndex]; 1167 let freeSize = maxSize - currentChunkOffset; 1168 if (currentArkTsData.length > freeSize) { 1169 let freeSaveData = currentArkTsData.slice(0, freeSize); 1170 currentChunk.set(freeSaveData, currentChunkOffset); 1171 let arg2 = setArg(currentChunk, fileType, pageNum, saveStartOffset, saveIndex, timStamp); 1172 await addDataToIndexeddb(indexDB, arg2); 1173 saveStartOffset += maxSize; 1174 saveIndex++; 1175 let remnantData = currentArkTsData.slice(freeSize); 1176 let remnantDataLength: number = Math.ceil(remnantData.length / maxSize); 1177 for (let newSliceIndex = 0; newSliceIndex < remnantDataLength; newSliceIndex++) { 1178 let newSliceSize = newSliceIndex * maxSize; 1179 let number = Math.min(newSliceSize + maxSize, remnantData.length); 1180 let saveArray = remnantData.slice(newSliceSize, number); 1181 if (newSliceIndex === remnantDataLength - 1 && number - newSliceSize < maxSize) { 1182 currentChunk = new Uint8Array(maxSize); 1183 currentChunkOffset = 0; 1184 currentChunk.set(saveArray, currentChunkOffset); 1185 currentChunkOffset += saveArray.length; 1186 } else { 1187 let arg2 = setArg(saveArray, fileType, pageNum, saveStartOffset, saveIndex, timStamp); 1188 await addDataToIndexeddb(indexDB, arg2); 1189 saveStartOffset += maxSize; 1190 saveIndex++; 1191 } 1192 } 1193 } else { 1194 currentChunk.set(currentArkTsData, currentChunkOffset); 1195 currentChunkOffset += currentArkTsData.length; 1196 } 1197 } 1198} 1199 1200const splitFileAndSave = async ( 1201 timStamp: number, 1202 fileInfo: { 1203 fileType: string; 1204 startIndex: number; 1205 endIndex: number; 1206 size: number; 1207 }, 1208 pageNum: number, 1209 splitBufAddr?: number 1210): Promise<void> => { 1211 let fileType = fileInfo.fileType; 1212 let fileSize = fileInfo.size; 1213 let startIndex = fileInfo.startIndex; 1214 let endIndex = fileInfo.endIndex; 1215 let queryStartIndex = startIndex; 1216 let queryEndIndex = startIndex; 1217 let saveIndex = 0; 1218 let saveStartOffset = 0; 1219 let current = new Uint8Array(maxSize); 1220 let currentOffset = 0; 1221 let resSize = 0; 1222 do { 1223 queryEndIndex = queryStartIndex + 9; 1224 if (queryEndIndex > endIndex) { 1225 queryEndIndex = endIndex; 1226 } 1227 let range = getRange(timStamp, fileType, queryStartIndex, queryEndIndex); 1228 let res = await getIndexedDBQueryData(indexDB, range); 1229 queryStartIndex = queryEndIndex + 1; 1230 //@ts-ignore 1231 for (let i = 0; i < res.length; i++) { 1232 //@ts-ignore 1233 let arrayBuffer = res[i]; 1234 let uint8Array = new Uint8Array(arrayBuffer.buf); 1235 let cutFileSize = 0; 1236 while (cutFileSize < uint8Array.length) { 1237 [cutFileSize, resSize] = splitLongTrace(pageNum, fileSize, resSize, cutFileSize, uint8Array, splitBufAddr); 1238 if (arkTsDataSize > 0 && fileType === 'arkts') { 1239 splitFileAndSaveArkTs(currentOffset, current, fileType, pageNum, saveStartOffset, saveIndex, timStamp); 1240 } 1241 } 1242 } 1243 } while (queryEndIndex < endIndex); 1244 if (fileType === 'arkts' && currentOffset > 0) { 1245 let remnantArray = new Uint8Array(currentOffset); 1246 let remnantChunk = current.slice(0, currentOffset); 1247 remnantArray.set(remnantChunk, 0); 1248 let arg2 = setArg(remnantArray, fileType, pageNum, saveStartOffset, saveIndex, timStamp); 1249 await addDataToIndexeddb(indexDB, arg2); 1250 arkTsDataSize = 0; 1251 arkTsData.length = 0; 1252 } 1253}; 1254 1255async function getIndexedDBQueryData(db: IDBDatabase, range: IDBKeyRange): Promise<unknown> { 1256 const transaction = db.transaction(STORE_NAME, 'readonly'); 1257 const store = transaction.objectStore(STORE_NAME); 1258 const index = store.index('QueryCompleteFile'); 1259 const getRequest = index.openCursor(range); 1260 return await queryDataFromIndexeddb(getRequest); 1261} 1262 1263function splitLongTrace( 1264 pageNum: number, 1265 fileSize: number, 1266 resultFileSize: number, 1267 cutFileSize: number, 1268 uint8Array: Uint8Array, 1269 splitReqBufferAddr?: number 1270): [number, number] { 1271 const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); 1272 const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); 1273 //@ts-ignore 1274 wasmModule.HEAPU8.set(dataSlice, splitReqBufferAddr); 1275 cutFileSize += sliceLen; 1276 resultFileSize += sliceLen; 1277 if (resultFileSize >= fileSize) { 1278 //@ts-ignore 1279 wasmModule._TraceStreamerLongTraceSplitFileEx(sliceLen, 1, pageNum); 1280 } else { 1281 //@ts-ignore 1282 wasmModule._TraceStreamerLongTraceSplitFileEx(sliceLen, 0, pageNum); 1283 } 1284 return [cutFileSize, resultFileSize]; 1285} 1286 1287function setArg( 1288 remnantArray: Uint8Array, 1289 fileType: string, 1290 pageNum: number, 1291 saveStartOffset: number, 1292 saveIndex: number, 1293 timStamp: number 1294): unknown { 1295 return { 1296 buf: remnantArray, 1297 id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, 1298 fileType: `${fileType}_new`, 1299 pageNum: pageNum, 1300 startOffset: saveStartOffset, 1301 endOffset: saveStartOffset + maxSize, 1302 index: saveIndex, 1303 timStamp: timStamp, 1304 }; 1305} 1306function getRange(timStamp: number, fileType: string, queryStartIndex: number, queryEndIndex: number): IDBKeyRange { 1307 return IDBKeyRange.bound( 1308 [timStamp, fileType, 0, queryStartIndex], 1309 [timStamp, fileType, 0, queryEndIndex], 1310 false, 1311 false 1312 ); 1313} 1314 1315enum DataTypeEnum { 1316 data, 1317 json, 1318} 1319 1320let uploadSoActionId: string = ''; 1321let uploadFileIndex: number = 0; 1322let uploadSoCallbackFn: Function; 1323let soFileList: Array<File | null> = []; 1324const failedArray: Array<string> = []; 1325const uploadSoFile = async (file: File | null): Promise<void> => { 1326 if (file) { 1327 let fileNameBuffer: Uint8Array | null = enc.encode(file.webkitRelativePath); 1328 let fileNameLength = fileNameBuffer.length; 1329 //@ts-ignore 1330 let addr = wasmModule._InitFileName(uploadSoCallbackFn, fileNameBuffer.length); 1331 //@ts-ignore 1332 wasmModule.HEAPU8.set(fileNameBuffer, addr); 1333 let writeSize = 0; 1334 let upRes = -1; 1335 while (writeSize < file.size) { 1336 let sliceLen = Math.min(file.size - writeSize, REQ_BUF_SIZE); 1337 let blob: Blob | null = file.slice(writeSize, writeSize + sliceLen); 1338 let buffer: ArrayBuffer | null = await blob.arrayBuffer(); 1339 let data: Uint8Array | null = new Uint8Array(buffer); 1340 let size = file.size; 1341 //@ts-ignore 1342 wasmModule.HEAPU8.set(data, reqBufferAddr); 1343 writeSize += sliceLen; 1344 //@ts-ignore 1345 upRes = wasmModule._TraceStreamerDownloadELFEx(size, fileNameLength, sliceLen, 1); 1346 data = null; 1347 buffer = null; 1348 blob = null; 1349 } 1350 file = null; 1351 soFileList[uploadFileIndex] = null; 1352 fileNameBuffer = null; 1353 } 1354}; 1355 1356const uploadSoCallBack = (heapPtr: number, size: number, isFinish: number): void => { 1357 //@ts-ignore 1358 let out: Uint8Array | null = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 1359 if (out) { 1360 let res = dec.decode(out); 1361 out = null; 1362 if (res.includes('ok') || res.includes('failed')) { 1363 if (res.includes('failed')) { 1364 failedArray.push(soFileList[uploadFileIndex]!.name); 1365 } 1366 if (uploadFileIndex < soFileList.length - 1) { 1367 uploadSoFile(soFileList[uploadFileIndex + 1]).then(); 1368 } 1369 uploadFileIndex++; 1370 } 1371 if (uploadFileIndex === soFileList.length) { 1372 soFileList.length = 0; 1373 const result = failedArray.length === 0 ? 'ok' : 'failed'; 1374 self.postMessage({ 1375 id: uploadSoActionId, 1376 action: 'upload-so', 1377 results: { result: result, failedArray: failedArray }, 1378 }); 1379 } 1380 } 1381}; 1382 1383let splitReqBufferAddr = -1; 1384 1385enum FileTypeEnum { 1386 data, 1387 json, 1388} 1389 1390function isRawTrace(uint8Array: Uint8Array): boolean { 1391 let rowTraceStr = Array.from(new Uint16Array(uint8Array.buffer.slice(0, 2))); 1392 return rowTraceStr[0] === 57161; 1393} 1394 1395function cutFileBufferByOffSet(out: Uint8Array, uint8Array: Uint8Array): Uint8Array { 1396 let jsonStr: string = dec.decode(out); 1397 let jsonObj = JSON.parse(jsonStr); 1398 let valueArray: Array<{ type: number; offset: number; size: number }> = jsonObj.value; 1399 let cutBuffer: Uint8Array; 1400 if (isRawTrace(uint8Array)) { 1401 let commDataSize = 0; 1402 let otherDataSize = 0; 1403 valueArray.forEach((item) => { 1404 const type = item.type; 1405 if (type === 0) { 1406 commDataSize += item.size; 1407 } else { 1408 otherDataSize += item.size; 1409 otherDataSize += 8; 1410 } 1411 }); 1412 cutBuffer = new Uint8Array(commDataSize + otherDataSize); 1413 let commOffset = 0; 1414 let tlvOffset = commDataSize; 1415 valueArray.forEach((item) => { 1416 if (item.type !== 0) { 1417 let typeArray = new Uint32Array(1); 1418 typeArray[0] = item.type; 1419 cutBuffer.set(new Uint8Array(typeArray.buffer), tlvOffset); 1420 tlvOffset += typeArray.byteLength; 1421 let lengthArray = new Uint32Array(1); 1422 lengthArray[0] = item.size; 1423 cutBuffer.set(new Uint8Array(lengthArray.buffer), tlvOffset); 1424 tlvOffset += typeArray.byteLength; 1425 const dataSlice = uint8Array.subarray(item.offset, item.offset + item.size); 1426 cutBuffer.set(dataSlice, tlvOffset); 1427 tlvOffset += item.size; 1428 } else { 1429 const dataSlice = uint8Array.subarray(item.offset, item.offset + item.size); 1430 cutBuffer.set(dataSlice, commOffset); 1431 commOffset += item.size; 1432 } 1433 }); 1434 } else { 1435 const sum = valueArray.reduce((total, obj) => total + obj.size, 0); 1436 cutBuffer = new Uint8Array(sum); 1437 let offset = 0; 1438 valueArray.forEach((item, index) => { 1439 const dataSlice = uint8Array.subarray(item.offset, item.offset + item.size); 1440 cutBuffer.set(dataSlice, offset); 1441 offset += item.size; 1442 }); 1443 } 1444 return cutBuffer; 1445} 1446 1447function cutFileByRange(e: MessageEvent): void { 1448 let cutLeftTs = e.data.leftTs; 1449 let cutRightTs = e.data.rightTs; 1450 let uint8Array = new Uint8Array(e.data.buffer); 1451 let resultBuffer: Array<Uint8Array> = []; 1452 let cutFileCallBack = cutFileCallBackFunc(resultBuffer, uint8Array, e); 1453 //@ts-ignore 1454 splitReqBufferAddr = wasmModule._InitializeSplitFile(wasmModule.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); 1455 let cutTimeRange = `${cutLeftTs};${cutRightTs};`; 1456 let cutTimeRangeBuffer = enc.encode(cutTimeRange); 1457 //@ts-ignore 1458 wasmModule.HEAPU8.set(cutTimeRangeBuffer, splitReqBufferAddr); 1459 //@ts-ignore 1460 wasmModule._TraceStreamerSplitFileEx(cutTimeRangeBuffer.length); 1461 let cutFileSize = 0; 1462 let receiveFileResult = -1; 1463 while (cutFileSize < uint8Array.length) { 1464 const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); 1465 const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); 1466 //@ts-ignore 1467 wasmModule.HEAPU8.set(dataSlice, splitReqBufferAddr); 1468 cutFileSize += sliceLen; 1469 try { 1470 if (cutFileSize >= uint8Array.length) { 1471 //@ts-ignore 1472 receiveFileResult = wasmModule._TraceStreamerReciveFileEx(sliceLen, 1); 1473 } else { 1474 //@ts-ignore 1475 receiveFileResult = wasmModule._TraceStreamerReciveFileEx(sliceLen, 0); 1476 } 1477 } catch (error) { 1478 self.postMessage( 1479 { 1480 id: e.data.id, 1481 action: e.data.action, 1482 cutStatus: false, 1483 msg: 'split failed', 1484 buffer: e.data.buffer, 1485 }, 1486 // @ts-ignore 1487 [e.data.buffer] 1488 ); 1489 } 1490 } 1491} 1492function cutFileCallBackFunc(resultBuffer: Array<Uint8Array>, uint8Array: Uint8Array, e: MessageEvent): Function { 1493 return (heapPtr: number, size: number, fileType: number, isEnd: number) => { 1494 //@ts-ignore 1495 let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); 1496 if (FileTypeEnum.data === fileType) { 1497 resultBuffer.push(out); 1498 } else if (FileTypeEnum.json === fileType) { 1499 let cutBuffer = cutFileBufferByOffSet(out, uint8Array); 1500 resultBuffer.push(cutBuffer); 1501 } 1502 if (isEnd) { 1503 //@ts-ignore 1504 const cutResultFileLength = resultBuffer.reduce((total, obj) => total + obj.length, 0); 1505 //@ts-ignore 1506 let cutBuffer = new Uint8Array(cutResultFileLength); 1507 let offset = 0; 1508 resultBuffer.forEach((item) => { 1509 //@ts-ignore 1510 cutBuffer.set(item, offset); 1511 //@ts-ignore 1512 offset += item.length; 1513 }); 1514 resultBuffer.length = 0; 1515 self.postMessage( 1516 { 1517 id: e.data.id, 1518 action: e.data.action, 1519 cutStatus: true, 1520 msg: 'split success', 1521 buffer: e.data.buffer, 1522 cutBuffer: cutBuffer.buffer, 1523 }, 1524 // @ts-ignore 1525 [e.data.buffer, cutBuffer.buffer] 1526 ); 1527 } 1528 }; 1529} 1530 1531function createView(sql: string): void { 1532 let array = enc.encode(sql); 1533 //@ts-ignore 1534 wasmModule.HEAPU8.set(array, reqBufferAddr); 1535 //@ts-ignore 1536 wasmModule._TraceStreamerSqlOperateEx(array.length); 1537} 1538 1539function query(name: string, sql: string, params: unknown): void { 1540 if (params) { 1541 Reflect.ownKeys(params).forEach((key: unknown) => { 1542 //@ts-ignore 1543 if (typeof params[key] === 'string') { 1544 //@ts-ignore 1545 sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${params[key]}'`); 1546 } else { 1547 //@ts-ignore 1548 sql = sql.replace(new RegExp(`\\${key}`, 'g'), params[key]); 1549 } 1550 }); 1551 } 1552 let sqlUintArray = enc.encode(sql); 1553 //@ts-ignore 1554 wasmModule.HEAPU8.set(sqlUintArray, reqBufferAddr); 1555 //@ts-ignore 1556 wasmModule._TraceStreamerSqlQueryEx(sqlUintArray.length); 1557} 1558 1559function querySdk(name: string, sql: string, sdkParams: unknown, action: string): void { 1560 if (sdkParams) { 1561 Reflect.ownKeys(sdkParams).forEach((key: unknown) => { 1562 //@ts-ignore 1563 if (typeof sdkParams[key] === 'string') { 1564 //@ts-ignore 1565 sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${sdkParams[key]}'`); 1566 } else { 1567 //@ts-ignore 1568 sql = sql.replace(new RegExp(`\\${key}`, 'g'), sdkParams[key]); 1569 } 1570 }); 1571 } 1572 let sqlUintArray = enc.encode(sql); 1573 let commentId = action.substring(action.lastIndexOf('-') + 1); 1574 let key = Number(commentId); 1575 let wasm = thirdWasmMap.get(key); 1576 if (wasm !== undefined) { 1577 let wasmModel = wasm.model; 1578 wasmModel.HEAPU8.set(sqlUintArray, wasm.bufferAddr); 1579 wasmModel._TraceStreamerSqlQueryEx(sqlUintArray.length); 1580 } 1581} 1582 1583function queryMetric(name: string): void { 1584 let metricArray = enc.encode(name); 1585 //@ts-ignore 1586 wasmModule.HEAPU8.set(metricArray, reqBufferAddr); 1587 //@ts-ignore 1588 wasmModule._TraceStreamerSqlMetricsQuery(metricArray.length); 1589} 1590 1591const DB_NAME = 'sp'; 1592const DB_VERSION = 1; 1593const STORE_NAME = 'longTable'; 1594 1595function openDB(): Promise<IDBDatabase> { 1596 return new Promise((resolve, reject) => { 1597 const openRequest = indexedDB.open(DB_NAME, DB_VERSION); 1598 openRequest.onerror = (): void => reject(openRequest.error); 1599 openRequest.onsuccess = (): void => { 1600 resolve(openRequest.result); 1601 }; 1602 }); 1603} 1604 1605function queryDataFromIndexeddb(getRequest: IDBRequest<IDBCursorWithValue | null>): Promise<unknown> { 1606 return new Promise((resolve, reject) => { 1607 let results: unknown[] = []; 1608 getRequest.onerror = (event): void => { 1609 // @ts-ignore 1610 reject(event.target.error); 1611 }; 1612 getRequest.onsuccess = (event): void => { 1613 // @ts-ignore 1614 const cursor = event.target!.result; 1615 if (cursor) { 1616 results.push(cursor.value); 1617 cursor.continue(); 1618 } else { 1619 // @ts-ignore 1620 resolve(results); 1621 } 1622 }; 1623 }); 1624} 1625 1626function addDataToIndexeddb(db: IDBDatabase, value: unknown, key?: IDBValidKey): Promise<unknown> { 1627 return new Promise((resolve, reject) => { 1628 const transaction = db.transaction(STORE_NAME, 'readwrite'); 1629 const objectStore = transaction.objectStore(STORE_NAME); 1630 const request = objectStore.add(value, key); 1631 request.onsuccess = function (event): void { 1632 // @ts-ignore 1633 resolve(event.target.result); 1634 }; 1635 request.onerror = (event): void => { 1636 reject(event); 1637 }; 1638 }); 1639} 1640