* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
importScripts('trace_streamer_builtin.js', 'TempSql.js');
let Module: any = null;
let enc = new TextEncoder();
let dec = new TextDecoder();
let arr: Uint8Array;
let start: number;
const REQ_BUF_SIZE = 4 * 1024 * 1024;
let reqBufferAddr: number = -1;
let bufferSlice: Array<any> = [];
let json: string;
let headUnitArray: Uint8Array;
let thirdWasmMap = new Map();
let thirdJsonResult = new Map();
let currentAction: string = '';
let currentActionId: string = '';
self.addEventListener('unhandledrejection', (err) => {
self.postMessage({
id: currentActionId,
action: currentAction,
init: false,
status: false,
msg: err.reason.message,
});
});
function initWASM() {
return new Promise((resolve, reject) => {
let wasm = trace_streamer_builtin_wasm;
Module = wasm({
locateFile: (s: any) => {
return s;
},
print: (line: any) => {},
printErr: (line: any) => {},
onRuntimeInitialized: () => {
resolve('ok');
},
onAbort: () => {
reject('on abort');
},
});
});
}
function initThirdWASM(wasmFunctionName: string) {
function callModelFun(functionName: string) {
let func = eval(functionName);
return new func({
locateFile: (s: any) => {
return s;
},
print: (line: any) => {},
printErr: (line: any) => {},
onRuntimeInitialized: () => {},
onAbort: () => {},
});
}
return callModelFun(wasmFunctionName);
}
let merged = () => {
let length = 0;
bufferSlice.forEach((item) => {
length += item.length;
});
let mergedArray = new Uint8Array(length);
let offset = 0;
bufferSlice.forEach((item) => {
mergedArray.set(item, offset);
offset += item.length;
});
return mergedArray;
};
let convertJSON = () => {
let str = dec.decode(arr);
let jsonArray = [];
str = str.substring(str.indexOf('\n') + 1);
if (!str) {
} else {
let parse = JSON.parse(translateJsonString(str));
let columns = parse.columns;
let values = parse.values;
for (let i = 0; i < values.length; i++) {
let obj: any = {};
for (let j = 0; j < columns.length; j++) {
obj[columns[j]] = values[i][j];
}
jsonArray.push(obj);
}
}
return jsonArray;
};
self.onmessage = async (e: MessageEvent) => {
currentAction = e.data.action;
currentActionId = e.data.id;
if (e.data.action === 'open') {
await initWASM();
self.postMessage({
id: e.data.id,
action: e.data.action,
ready: true,
index: 0,
});
let uint8Array = new Uint8Array(e.data.buffer);
let callback = (heapPtr: number, size: number, isEnd: number) => {
let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size);
bufferSlice.push(out);
if (isEnd == 1) {
arr = merged();
bufferSlice.length = 0;
}
};
let fn = Module.addFunction(callback, 'viii');
reqBufferAddr = Module._Initialize(fn, REQ_BUF_SIZE);
let wasmConfigStr = e.data.wasmConfig;
if (wasmConfigStr != '' && wasmConfigStr.indexOf('WasmFiles') != -1) {
let wasmConfig = JSON.parse(wasmConfigStr);
let wasmConfigs = wasmConfig.WasmFiles;
let itemArray = wasmConfigs.map((item: any) => {
return item.componentId + ';' + item.pluginName;
});
let thirdWasmStr: string = itemArray.join(';');
let configUintArray = enc.encode(thirdWasmStr + ';');
Module.HEAPU8.set(configUintArray, reqBufferAddr);
Module._TraceStreamer_Init_ThirdParty_Config(configUintArray.length);
let first = true;
let sendDataCallback = (heapPtr: number, size: number, componentID: number) => {
if (componentID == 100) {
if (first) {
first = false;
headUnitArray = Module.HEAPU8.slice(heapPtr, heapPtr + size);
}
return;
}
let configs = wasmConfigs.filter((wasmConfig: any) => {
return wasmConfig.componentId == componentID;
});
if (configs.length > 0) {
let config = configs[0];
let model = thirdWasmMap.get(componentID);
if (model == null && config.componentId == componentID) {
importScripts(config.wasmJsName);
let thirdMode = initThirdWASM(config.wasmName);
let configPluginName = config.pluginName;
let pluginNameUintArray = enc.encode(configPluginName);
let pluginNameBuffer = thirdMode._InitPluginName(pluginNameUintArray.length);
thirdMode.HEAPU8.set(pluginNameUintArray, pluginNameBuffer);
thirdMode._TraceStreamerGetPluginNameEx(configPluginName.length);
let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => {
if (isConfig == 1) {
let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size);
thirdJsonResult.set(componentID, {
jsonConfig: dec.decode(out),
disPlayName: config.disPlayName,
pluginName: config.pluginName,
});
} else {
let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size);
bufferSlice.push(out);
if (isEnd == 1) {
arr = merged();
bufferSlice.length = 0;
}
}
};
let fn = thirdMode.addFunction(thirdQueryDataCallBack, 'viiii');
let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE);
let updateTraceTimeCallBack = (heapPtr: number, size: number) => {
let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size);
Module.HEAPU8.set(out, reqBufferAddr);
Module._UpdateTraceTime(out.length);
};
let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, 'vii');
let mm = thirdMode._InitTraceRange(traceRangeFn, 1024);
thirdMode._TraceStreamer_In_JsonConfig();
thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr);
thirdMode._ParserData(headUnitArray.length, 100);
let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size);
thirdMode.HEAPU8.set(out, thirdreqBufferAddr);
thirdMode._ParserData(out.length, componentID);
thirdWasmMap.set(componentID, {
model: thirdMode,
bufferAddr: thirdreqBufferAddr,
});
} else {
let mm = model.model;
let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size);
mm.HEAPU8.set(out, model.bufferAddr);
mm._ParserData(out.length, componentID);
}
}
};
let fn1 = Module.addFunction(sendDataCallback, 'viii');
let reqBufferAddr1 = Module._TraceStreamer_Set_ThirdParty_DataDealer(fn1, REQ_BUF_SIZE);
}
let wrSize = 0;
let r2 = -1;
while (wrSize < uint8Array.length) {
const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE);
const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen);
Module.HEAPU8.set(dataSlice, reqBufferAddr);
wrSize += sliceLen;
r2 = Module._TraceStreamerParseDataEx(sliceLen);
if (r2 == -1) {
break;
}
}
Module._TraceStreamerParseDataOver();
for (let value of thirdWasmMap.values()) {
value.model._TraceStreamer_In_ParseDataOver();
}
if (r2 == -1) {
self.postMessage({
id: e.data.id,
action: e.data.action,
init: false,
msg: 'parse data error',
});
return;
}
temp_init_sql_list.forEach((item, index) => {
let r = createView(item);
self.postMessage({ id: e.data.id, ready: true, index: index + 1 });
});
self.postMessage(
{
id: e.data.id,
action: e.data.action,
init: true,
msg: 'ok',
configSqlMap: thirdJsonResult,
buffer: e.data.buffer,
},
[e.data.buffer]
);
} else if (e.data.action === 'exec') {
query(e.data.name, e.data.sql, e.data.params);
let jsonArray = convertJSON();
self.postMessage({
id: e.data.id,
action: e.data.action,
results: jsonArray,
});
} else if (e.data.action == 'exec-buf') {
query(e.data.name, e.data.sql, e.data.params);
self.postMessage(
{ id: e.data.id, action: e.data.action, results: arr.buffer },
[arr.buffer]
);
} else if (e.data.action.startsWith('exec-sdk')) {
querySdk(e.data.name, e.data.sql, e.data.params, e.data.action);
let jsonArray = convertJSON();
self.postMessage({
id: e.data.id,
action: e.data.action,
results: jsonArray,
});
} else if (e.data.action == 'init-port') {
let port = e.ports[0];
port.onmessage = (me) => {
query(me.data.action, me.data.sql, me.data.params);
let msg = {
id: me.data.id,
action: me.data.action,
results: arr.buffer,
};
port.postMessage(msg, [arr.buffer]);
};
} else if (e.data.action == 'download-db') {
let bufferSliceUint: Array<any> = [];
let mergedUint = () => {
let length = 0;
bufferSliceUint.forEach((item) => {
length += item.length;
});
let mergedArray = new Uint8Array(length);
let offset = 0;
bufferSliceUint.forEach((item) => {
mergedArray.set(item, offset);
offset += item.length;
});
return mergedArray;
};
let getDownloadDb = (heapPtr: number, size: number, isEnd: number) => {
let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size);
bufferSliceUint.push(out);
if (isEnd == 1) {
let arr: Uint8Array = mergedUint();
self.postMessage({
id: e.data.id,
action: e.data.action,
results: arr,
});
}
};
let fn1 = Module.addFunction(getDownloadDb, 'viii');
Module._WasmExportDatabase(fn1);
} else if (e.data.action === 'upload-so') {
let fileList = e.data.params as Array<File>;
if (fileList) {
uploadSoFile(fileList, () => {
self.postMessage({
id: e.data.id,
action: e.data.action,
results: 'ok',
});
});
}
}
};
let uploadFileIndex: number = 0;
function uploadSoFile(files: Array<File>, callback: () => void) {
let uploadFile = (file: File) => {
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onloadend = function (ev) {
if (this.result) {
let fileNameBuffer = enc.encode(file.webkitRelativePath);
let addr = Module._InitFileName(fn, fileNameBuffer.length);
Module.HEAPU8.set(fileNameBuffer, addr);
let data = new Uint8Array(this.result as ArrayBuffer);
let writeSize = 0;
let upRes = -1;
while (writeSize < data.length) {
const sliceLen = Math.min(data.length - writeSize, REQ_BUF_SIZE);
const dataSlice = data.subarray(writeSize, writeSize + sliceLen);
Module.HEAPU8.set(dataSlice, reqBufferAddr);
writeSize += sliceLen;
upRes = Module._TraceStreamerDownloadELFEx(
data.length,
fileNameBuffer.length,
sliceLen,
files.length,
uploadFileIndex === files.length - 1 ? 1 : 0
);
}
}
};
};
let uploadSoCallBack = (heapPtr: number, size: number, isFinish: number) => {
let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size);
let res = dec.decode(out);
if (res.includes('file send over')) {
if (uploadFileIndex < files.length - 1) {
uploadFileIndex = uploadFileIndex + 1;
uploadFile(files[uploadFileIndex]);
}
}
if (res.includes('ok')) {
callback();
}
};
let fn = Module.addFunction(uploadSoCallBack, 'viii');
uploadFileIndex = 0;
if (files.length > 0) {
uploadFile(files[uploadFileIndex]);
}
}
function createView(sql: string) {
let array = enc.encode(sql);
Module.HEAPU8.set(array, reqBufferAddr);
let res = Module._TraceStreamerSqlOperateEx(array.length);
return res;
}
function queryJSON(name: string, sql: string, params: any) {
query(name, sql, params);
return convertJSON();
}
function query(name: string, sql: string, params: any) {
if (params) {
Reflect.ownKeys(params).forEach((key: any) => {
if (typeof params[key] === 'string') {
sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${params[key]}'`);
} else {
sql = sql.replace(new RegExp(`\\${key}`, 'g'), params[key]);
}
});
}
start = new Date().getTime();
let sqlUintArray = enc.encode(sql);
Module.HEAPU8.set(sqlUintArray, reqBufferAddr);
Module._TraceStreamerSqlQueryEx(sqlUintArray.length);
}
function querySdk(name: string, sql: string, params: any, action: string) {
if (params) {
Reflect.ownKeys(params).forEach((key: any) => {
if (typeof params[key] === 'string') {
sql = sql.replace(new RegExp(`\\${key}`, 'g'), `'${params[key]}'`);
} else {
sql = sql.replace(new RegExp(`\\${key}`, 'g'), params[key]);
}
});
}
let sqlUintArray = enc.encode(sql);
let commentId = action.substring(action.lastIndexOf('-') + 1);
let key = Number(commentId);
let wasm = thirdWasmMap.get(key);
if (wasm != undefined) {
let wasmModel = wasm.model;
wasmModel.HEAPU8.set(sqlUintArray, wasm.bufferAddr);
wasmModel._TraceStreamerSqlQueryEx(sqlUintArray.length);
}
}