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