1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciclass DbThread {
17fb726d48Sopenharmony_ci  busy: boolean = false;
18fb726d48Sopenharmony_ci  id: number = -1;
19fb726d48Sopenharmony_ci  //@ts-ignore
20fb726d48Sopenharmony_ci  taskMap: unknow = {};
21fb726d48Sopenharmony_ci  worker?: Worker;
22fb726d48Sopenharmony_ci  traceId: string;
23fb726d48Sopenharmony_ci
24fb726d48Sopenharmony_ci  constructor(worker: Worker, traceId: string) {
25fb726d48Sopenharmony_ci    this.worker = worker;
26fb726d48Sopenharmony_ci    this.traceId = traceId;
27fb726d48Sopenharmony_ci  }
28fb726d48Sopenharmony_ci
29fb726d48Sopenharmony_ci  uuid(): string {
30fb726d48Sopenharmony_ci    // @ts-ignore
31fb726d48Sopenharmony_ci    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: unknow) =>
32fb726d48Sopenharmony_ci      (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
33fb726d48Sopenharmony_ci    );
34fb726d48Sopenharmony_ci  }
35fb726d48Sopenharmony_ci
36fb726d48Sopenharmony_ci  //@ts-ignore
37fb726d48Sopenharmony_ci  queryFunc(name: string, sql: string, args: unknow, handler: Function, action: string | null): void {
38fb726d48Sopenharmony_ci    this.busy = true;
39fb726d48Sopenharmony_ci    let id = this.uuid();
40fb726d48Sopenharmony_ci    this.taskMap[id] = handler;
41fb726d48Sopenharmony_ci    let msg = {
42fb726d48Sopenharmony_ci      id: id,
43fb726d48Sopenharmony_ci      name: name,
44fb726d48Sopenharmony_ci      action: action || 'exec',
45fb726d48Sopenharmony_ci      sql: sql,
46fb726d48Sopenharmony_ci      params: args,
47fb726d48Sopenharmony_ci    };
48fb726d48Sopenharmony_ci    this.worker?.postMessage(msg);
49fb726d48Sopenharmony_ci  }
50fb726d48Sopenharmony_ci
51fb726d48Sopenharmony_ci  //@ts-ignore
52fb726d48Sopenharmony_ci  queryProto(name: number, args: unknow, handler: Function): void {
53fb726d48Sopenharmony_ci    this.busy = true;
54fb726d48Sopenharmony_ci    let id = this.uuid();
55fb726d48Sopenharmony_ci    this.taskMap[id] = handler;
56fb726d48Sopenharmony_ci    let msg = {
57fb726d48Sopenharmony_ci      id: id,
58fb726d48Sopenharmony_ci      name: name,
59fb726d48Sopenharmony_ci      action: 'exec-proto',
60fb726d48Sopenharmony_ci      params: args,
61fb726d48Sopenharmony_ci    };
62fb726d48Sopenharmony_ci    this.worker?.postMessage(msg);
63fb726d48Sopenharmony_ci  }
64fb726d48Sopenharmony_ci
65fb726d48Sopenharmony_ci  cutFileByRange(
66fb726d48Sopenharmony_ci    leftTs: number,
67fb726d48Sopenharmony_ci    rightTs: number,
68fb726d48Sopenharmony_ci    handler: (status: boolean, msg: string, splitBuffer?: ArrayBuffer) => void
69fb726d48Sopenharmony_ci  ): void {
70fb726d48Sopenharmony_ci    this.busy = true;
71fb726d48Sopenharmony_ci    let id = this.uuid();
72fb726d48Sopenharmony_ci    //@ts-ignore
73fb726d48Sopenharmony_ci    this.taskMap[id] = (res: unknow): void => {
74fb726d48Sopenharmony_ci      setThreadPoolTraceBuffer(this.traceId, res.buffer);
75fb726d48Sopenharmony_ci      if (res.cutStatus) {
76fb726d48Sopenharmony_ci        handler(res.cutStatus, res.msg, res.cutBuffer);
77fb726d48Sopenharmony_ci      } else {
78fb726d48Sopenharmony_ci        handler(res.cutStatus, res.msg);
79fb726d48Sopenharmony_ci      }
80fb726d48Sopenharmony_ci    };
81fb726d48Sopenharmony_ci    caches.match(getThreadPoolTraceBufferCacheKey(this.traceId)).then((resData) => {
82fb726d48Sopenharmony_ci      if (resData) {
83fb726d48Sopenharmony_ci        resData.arrayBuffer().then((buffer) => {
84fb726d48Sopenharmony_ci          this.worker!.postMessage(
85fb726d48Sopenharmony_ci            {
86fb726d48Sopenharmony_ci              id: id,
87fb726d48Sopenharmony_ci              action: 'cut-file',
88fb726d48Sopenharmony_ci              leftTs: leftTs,
89fb726d48Sopenharmony_ci              rightTs: rightTs,
90fb726d48Sopenharmony_ci              buffer: buffer!,
91fb726d48Sopenharmony_ci            },
92fb726d48Sopenharmony_ci            [buffer!]
93fb726d48Sopenharmony_ci          );
94fb726d48Sopenharmony_ci        });
95fb726d48Sopenharmony_ci      }
96fb726d48Sopenharmony_ci    });
97fb726d48Sopenharmony_ci  }
98fb726d48Sopenharmony_ci
99fb726d48Sopenharmony_ci  dbOpen = async (
100fb726d48Sopenharmony_ci    parseConfig: string,
101fb726d48Sopenharmony_ci    sdkWasmConfig?: string,
102fb726d48Sopenharmony_ci    buffer?: ArrayBuffer
103fb726d48Sopenharmony_ci  ): Promise<{
104fb726d48Sopenharmony_ci    status: boolean;
105fb726d48Sopenharmony_ci    msg: string;
106fb726d48Sopenharmony_ci    buffer: ArrayBuffer;
107fb726d48Sopenharmony_ci    //@ts-ignore
108fb726d48Sopenharmony_ci    sdkConfigMap: unknow;
109fb726d48Sopenharmony_ci    fileKey: string;
110fb726d48Sopenharmony_ci  }> => {
111fb726d48Sopenharmony_ci    //@ts-ignore
112fb726d48Sopenharmony_ci    return new Promise<unknow>((resolve, reject) => {
113fb726d48Sopenharmony_ci      let id = this.uuid();
114fb726d48Sopenharmony_ci      //@ts-ignore
115fb726d48Sopenharmony_ci      this.taskMap[id] = (res: unknow): unknow => {
116fb726d48Sopenharmony_ci        if (res.init) {
117fb726d48Sopenharmony_ci          resolve({
118fb726d48Sopenharmony_ci            status: res.init,
119fb726d48Sopenharmony_ci            msg: res.msg,
120fb726d48Sopenharmony_ci            sdkConfigMap: res.configSqlMap,
121fb726d48Sopenharmony_ci            buffer: res.buffer,
122fb726d48Sopenharmony_ci            fileKey: res.fileKey,
123fb726d48Sopenharmony_ci          });
124fb726d48Sopenharmony_ci        } else {
125fb726d48Sopenharmony_ci          resolve({ status: res.init, msg: res.msg });
126fb726d48Sopenharmony_ci        }
127fb726d48Sopenharmony_ci      };
128fb726d48Sopenharmony_ci      this.worker?.postMessage(
129fb726d48Sopenharmony_ci        {
130fb726d48Sopenharmony_ci          id: id,
131fb726d48Sopenharmony_ci          action: 'open',
132fb726d48Sopenharmony_ci          parseConfig: parseConfig,
133fb726d48Sopenharmony_ci          wasmConfig: sdkWasmConfig,
134fb726d48Sopenharmony_ci          buffer: buffer! /*Optional. An ArrayBuffer representing an SQLite Database file*/,
135fb726d48Sopenharmony_ci        },
136fb726d48Sopenharmony_ci        [buffer!]
137fb726d48Sopenharmony_ci      );
138fb726d48Sopenharmony_ci    });
139fb726d48Sopenharmony_ci  };
140fb726d48Sopenharmony_ci
141fb726d48Sopenharmony_ci  resetWASM(): void {
142fb726d48Sopenharmony_ci    this.worker?.postMessage({
143fb726d48Sopenharmony_ci      id: this.uuid(),
144fb726d48Sopenharmony_ci      action: 'reset',
145fb726d48Sopenharmony_ci    });
146fb726d48Sopenharmony_ci  }
147fb726d48Sopenharmony_ci}
148fb726d48Sopenharmony_ci
149fb726d48Sopenharmony_ciexport class DbPool {
150fb726d48Sopenharmony_ci  sharedBuffer: ArrayBuffer | null = null;
151fb726d48Sopenharmony_ci  fileCacheKey: string = 'null';
152fb726d48Sopenharmony_ci  traceId: string;
153fb726d48Sopenharmony_ci  maxThreadNumber: number = 0;
154fb726d48Sopenharmony_ci  works: Array<DbThread> = [];
155fb726d48Sopenharmony_ci  progress: Function | undefined | null;
156fb726d48Sopenharmony_ci  num = Math.floor(Math.random() * 10 + 1) + 20;
157fb726d48Sopenharmony_ci  cutDownTimer: unknown | undefined;
158fb726d48Sopenharmony_ci  currentWasmThread: DbThread | undefined = undefined;
159fb726d48Sopenharmony_ci
160fb726d48Sopenharmony_ci  constructor(traceId: string) {
161fb726d48Sopenharmony_ci    this.traceId = traceId;
162fb726d48Sopenharmony_ci  }
163fb726d48Sopenharmony_ci
164fb726d48Sopenharmony_ci  init = async (type: string, threadBuild: (() => DbThread) | undefined = undefined): Promise<void> => {
165fb726d48Sopenharmony_ci    // wasm | server | sqlite
166fb726d48Sopenharmony_ci    if (this.currentWasmThread) {
167fb726d48Sopenharmony_ci      this.currentWasmThread.resetWASM();
168fb726d48Sopenharmony_ci      this.currentWasmThread = undefined;
169fb726d48Sopenharmony_ci    }
170fb726d48Sopenharmony_ci    await this.close();
171fb726d48Sopenharmony_ci    this.maxThreadNumber = 1;
172fb726d48Sopenharmony_ci    for (let i = 0; i < this.maxThreadNumber; i++) {
173fb726d48Sopenharmony_ci      let thread: DbThread | undefined;
174fb726d48Sopenharmony_ci      if (threadBuild) {
175fb726d48Sopenharmony_ci        thread = threadBuild();
176fb726d48Sopenharmony_ci      } else {
177fb726d48Sopenharmony_ci        if (type === 'wasm') {
178fb726d48Sopenharmony_ci          thread = new DbThread(new Worker(new URL('./TraceWorker', import.meta.url)), this.traceId);
179fb726d48Sopenharmony_ci        } else if (type === 'server') {
180fb726d48Sopenharmony_ci          thread = new DbThread(new Worker(new URL('./SqlLiteWorker', import.meta.url)), this.traceId);
181fb726d48Sopenharmony_ci        } else if (type === 'sqlite') {
182fb726d48Sopenharmony_ci          thread = new DbThread(new Worker(new URL('./SqlLiteWorker', import.meta.url)), this.traceId);
183fb726d48Sopenharmony_ci        }
184fb726d48Sopenharmony_ci      }
185fb726d48Sopenharmony_ci      if (thread) {
186fb726d48Sopenharmony_ci        this.currentWasmThread = thread;
187fb726d48Sopenharmony_ci        thread!.worker!.onerror = (err): void => {
188fb726d48Sopenharmony_ci          console.warn(err);
189fb726d48Sopenharmony_ci        };
190fb726d48Sopenharmony_ci        thread!.worker!.onmessageerror = (err): void => {
191fb726d48Sopenharmony_ci          console.warn(err);
192fb726d48Sopenharmony_ci        };
193fb726d48Sopenharmony_ci        this.threadPostMessage(thread);
194fb726d48Sopenharmony_ci        thread!.id = i;
195fb726d48Sopenharmony_ci        thread!.busy = false;
196fb726d48Sopenharmony_ci        this.works?.push(thread!);
197fb726d48Sopenharmony_ci      }
198fb726d48Sopenharmony_ci    }
199fb726d48Sopenharmony_ci  };
200fb726d48Sopenharmony_ci  threadPostMessage(thread: DbThread): void {
201fb726d48Sopenharmony_ci    thread!.worker!.onmessage = (event: MessageEvent): void => {
202fb726d48Sopenharmony_ci      thread!.busy = false;
203fb726d48Sopenharmony_ci      if (Reflect.has(thread!.taskMap, event.data.id)) {
204fb726d48Sopenharmony_ci        if (event.data.results) {
205fb726d48Sopenharmony_ci          let fun = thread!.taskMap[event.data.id];
206fb726d48Sopenharmony_ci          if (fun) {
207fb726d48Sopenharmony_ci            fun(event.data.results, event.data.len, event.data.transfer, event.data.isEmpty);
208fb726d48Sopenharmony_ci          }
209fb726d48Sopenharmony_ci          Reflect.deleteProperty(thread!.taskMap, event.data.id);
210fb726d48Sopenharmony_ci        } else if (Reflect.has(event.data, 'cutStatus')) {
211fb726d48Sopenharmony_ci          let fun = thread!.taskMap[event.data.id];
212fb726d48Sopenharmony_ci          if (fun) {
213fb726d48Sopenharmony_ci            fun(event.data);
214fb726d48Sopenharmony_ci          }
215fb726d48Sopenharmony_ci        } else if (Reflect.has(event.data, 'ready')) {
216fb726d48Sopenharmony_ci          this.progress!('database opened', this.num + event.data.index);
217fb726d48Sopenharmony_ci          this.progressTimer(this.num + event.data.index, this.progress!);
218fb726d48Sopenharmony_ci          this.sharedBuffer = null;
219fb726d48Sopenharmony_ci        } else if (Reflect.has(event.data, 'init')) {
220fb726d48Sopenharmony_ci          if (this.cutDownTimer !== undefined) {
221fb726d48Sopenharmony_ci            //@ts-ignore
222fb726d48Sopenharmony_ci            clearInterval(this.cutDownTimer);
223fb726d48Sopenharmony_ci          }
224fb726d48Sopenharmony_ci          let fun = thread!.taskMap[event.data.id];
225fb726d48Sopenharmony_ci          if (!event.data.init && !event.data.status) {
226fb726d48Sopenharmony_ci            if (fun) {
227fb726d48Sopenharmony_ci              fun(['error', event.data.msg]);
228fb726d48Sopenharmony_ci            }
229fb726d48Sopenharmony_ci          } else {
230fb726d48Sopenharmony_ci            this.progress!('database ready', 40);
231fb726d48Sopenharmony_ci            if (fun) {
232fb726d48Sopenharmony_ci              fun(event.data);
233fb726d48Sopenharmony_ci            }
234fb726d48Sopenharmony_ci          }
235fb726d48Sopenharmony_ci          Reflect.deleteProperty(thread!.taskMap, event.data.id);
236fb726d48Sopenharmony_ci        } else {
237fb726d48Sopenharmony_ci          let fun = thread!.taskMap[event.data.id];
238fb726d48Sopenharmony_ci          if (fun) {
239fb726d48Sopenharmony_ci            fun([]);
240fb726d48Sopenharmony_ci          }
241fb726d48Sopenharmony_ci          Reflect.deleteProperty(thread!.taskMap, event.data.id);
242fb726d48Sopenharmony_ci        }
243fb726d48Sopenharmony_ci      }
244fb726d48Sopenharmony_ci    };
245fb726d48Sopenharmony_ci  }
246fb726d48Sopenharmony_ci
247fb726d48Sopenharmony_ci  initServer = async (url: string, progress: Function): Promise<{ status: boolean; msg: string }> => {
248fb726d48Sopenharmony_ci    this.progress = progress;
249fb726d48Sopenharmony_ci    progress('database loaded', 15);
250fb726d48Sopenharmony_ci    this.sharedBuffer = await fetch(url).then((res) => res.arrayBuffer());
251fb726d48Sopenharmony_ci    progress('open database', 20);
252fb726d48Sopenharmony_ci    for (let thread of this.works) {
253fb726d48Sopenharmony_ci      let { status, msg } = await thread.dbOpen('');
254fb726d48Sopenharmony_ci      if (!status) {
255fb726d48Sopenharmony_ci        this.sharedBuffer = null;
256fb726d48Sopenharmony_ci        return { status, msg };
257fb726d48Sopenharmony_ci      }
258fb726d48Sopenharmony_ci    }
259fb726d48Sopenharmony_ci    return { status: true, msg: 'ok' };
260fb726d48Sopenharmony_ci  };
261fb726d48Sopenharmony_ci  initSqlite = async (
262fb726d48Sopenharmony_ci    buf: ArrayBuffer,
263fb726d48Sopenharmony_ci    parseConfig: string,
264fb726d48Sopenharmony_ci    sdkWasmConfig: string,
265fb726d48Sopenharmony_ci    progress: Function
266fb726d48Sopenharmony_ci  ): Promise<
267fb726d48Sopenharmony_ci    | {
268fb726d48Sopenharmony_ci      status: false;
269fb726d48Sopenharmony_ci      msg: string;
270fb726d48Sopenharmony_ci      sdkConfigMap?: undefined;
271fb726d48Sopenharmony_ci    }
272fb726d48Sopenharmony_ci    | {
273fb726d48Sopenharmony_ci      status: boolean;
274fb726d48Sopenharmony_ci      msg: string;
275fb726d48Sopenharmony_ci      //@ts-ignore
276fb726d48Sopenharmony_ci      sdkConfigMap: unknow;
277fb726d48Sopenharmony_ci    }
278fb726d48Sopenharmony_ci  > => {
279fb726d48Sopenharmony_ci    this.progress = progress;
280fb726d48Sopenharmony_ci    progress('database loaded', 15);
281fb726d48Sopenharmony_ci    this.sharedBuffer = buf;
282fb726d48Sopenharmony_ci    progress('parse database', 20);
283fb726d48Sopenharmony_ci    let configMap;
284fb726d48Sopenharmony_ci    for (let thread of this.works) {
285fb726d48Sopenharmony_ci      let { status, msg, buffer, sdkConfigMap, fileKey } = await thread.dbOpen(parseConfig, sdkWasmConfig, buf);
286fb726d48Sopenharmony_ci      if (!status) {
287fb726d48Sopenharmony_ci        this.sharedBuffer = null;
288fb726d48Sopenharmony_ci        return { status, msg };
289fb726d48Sopenharmony_ci      } else {
290fb726d48Sopenharmony_ci        configMap = sdkConfigMap;
291fb726d48Sopenharmony_ci        this.sharedBuffer = buffer;
292fb726d48Sopenharmony_ci        if (fileKey !== '-1') {
293fb726d48Sopenharmony_ci          this.fileCacheKey = fileKey;
294fb726d48Sopenharmony_ci        } else {
295fb726d48Sopenharmony_ci          this.fileCacheKey = `trace/${new Date().getTime()}-${buffer.byteLength}`;
296fb726d48Sopenharmony_ci          this.saveTraceFileBuffer(this.fileCacheKey, buffer).then();
297fb726d48Sopenharmony_ci        }
298fb726d48Sopenharmony_ci      }
299fb726d48Sopenharmony_ci    }
300fb726d48Sopenharmony_ci    return { status: true, msg: 'ok', sdkConfigMap: configMap };
301fb726d48Sopenharmony_ci  };
302fb726d48Sopenharmony_ci
303fb726d48Sopenharmony_ci  async saveTraceFileBuffer(key: string, buffer: ArrayBuffer): Promise<void> {
304fb726d48Sopenharmony_ci    await this.obligateFileBufferSpace(buffer.byteLength);
305fb726d48Sopenharmony_ci    caches.open(key).then((cache) => {
306fb726d48Sopenharmony_ci      let headers = new Headers();
307fb726d48Sopenharmony_ci      headers.append('Content-Length', `${buffer.byteLength}`);
308fb726d48Sopenharmony_ci      headers.append('Content-Type', 'application/octet-stream');
309fb726d48Sopenharmony_ci      cache
310fb726d48Sopenharmony_ci        .put(
311fb726d48Sopenharmony_ci          key,
312fb726d48Sopenharmony_ci          new Response(buffer, {
313fb726d48Sopenharmony_ci            status: 200,
314fb726d48Sopenharmony_ci            headers: headers,
315fb726d48Sopenharmony_ci          })
316fb726d48Sopenharmony_ci        )
317fb726d48Sopenharmony_ci        .then();
318fb726d48Sopenharmony_ci    });
319fb726d48Sopenharmony_ci  }
320fb726d48Sopenharmony_ci
321fb726d48Sopenharmony_ci  /**
322fb726d48Sopenharmony_ci   * 计算预留缓存空间,如果空间不够,则删除部分缓存
323fb726d48Sopenharmony_ci   * @param size
324fb726d48Sopenharmony_ci   */
325fb726d48Sopenharmony_ci  async obligateFileBufferSpace(size: number): Promise<void> {
326fb726d48Sopenharmony_ci    let es = await navigator.storage.estimate();
327fb726d48Sopenharmony_ci    let remainderByte = (es.quota || 0) - (es.usage || 0) - 20 * 1024 * 1024;
328fb726d48Sopenharmony_ci    if (remainderByte < size) {
329fb726d48Sopenharmony_ci      let keys = await caches.keys();
330fb726d48Sopenharmony_ci      keys.sort((keyA, keyB) => {
331fb726d48Sopenharmony_ci        if (keyA.includes('/') && keyB.includes('/')) {
332fb726d48Sopenharmony_ci          let splitA = keyA.split('/');
333fb726d48Sopenharmony_ci          let splitB = keyB.split('/');
334fb726d48Sopenharmony_ci          let timeA = splitA[splitA.length - 1].split('-')[0];
335fb726d48Sopenharmony_ci          let timeB = splitB[splitB.length - 1].split('-')[0];
336fb726d48Sopenharmony_ci          return parseInt(timeA) - parseInt(timeB);
337fb726d48Sopenharmony_ci        } else {
338fb726d48Sopenharmony_ci          return 0;
339fb726d48Sopenharmony_ci        }
340fb726d48Sopenharmony_ci      });
341fb726d48Sopenharmony_ci      let needSize = size - remainderByte;
342fb726d48Sopenharmony_ci      for (let key of keys) {
343fb726d48Sopenharmony_ci        await caches.delete(key);
344fb726d48Sopenharmony_ci        let keySize = parseInt(key.split('-')[1]);
345fb726d48Sopenharmony_ci        if (keySize > needSize) {
346fb726d48Sopenharmony_ci          return;
347fb726d48Sopenharmony_ci        } else {
348fb726d48Sopenharmony_ci          needSize -= keySize;
349fb726d48Sopenharmony_ci        }
350fb726d48Sopenharmony_ci      }
351fb726d48Sopenharmony_ci    }
352fb726d48Sopenharmony_ci  }
353fb726d48Sopenharmony_ci
354fb726d48Sopenharmony_ci  close = async (): Promise<void> => {
355fb726d48Sopenharmony_ci    //@ts-ignore
356fb726d48Sopenharmony_ci    clearInterval(this.cutDownTimer);
357fb726d48Sopenharmony_ci    for (let thread of this.works) {
358fb726d48Sopenharmony_ci      thread.worker?.terminate();
359fb726d48Sopenharmony_ci    }
360fb726d48Sopenharmony_ci    this.works.length = 0;
361fb726d48Sopenharmony_ci  };
362fb726d48Sopenharmony_ci
363fb726d48Sopenharmony_ci  async reset(): Promise<void> {
364fb726d48Sopenharmony_ci    if (this.currentWasmThread) {
365fb726d48Sopenharmony_ci      this.currentWasmThread.resetWASM();
366fb726d48Sopenharmony_ci      this.currentWasmThread = undefined;
367fb726d48Sopenharmony_ci    }
368fb726d48Sopenharmony_ci    await this.close();
369fb726d48Sopenharmony_ci  }
370fb726d48Sopenharmony_ci
371fb726d48Sopenharmony_ci  //@ts-ignore
372fb726d48Sopenharmony_ci  submit(name: string, sql: string, args: unknow, handler: Function, action: string | null): void {
373fb726d48Sopenharmony_ci    let noBusyThreads = this.works.filter((it) => !it.busy);
374fb726d48Sopenharmony_ci    let thread: DbThread;
375fb726d48Sopenharmony_ci    if (noBusyThreads.length > 0) {
376fb726d48Sopenharmony_ci      //取第一个空闲的线程进行任务
377fb726d48Sopenharmony_ci      thread = noBusyThreads[0];
378fb726d48Sopenharmony_ci      thread.queryFunc(name, sql, args, handler, action);
379fb726d48Sopenharmony_ci    } else {
380fb726d48Sopenharmony_ci      // 随机插入一个线程中
381fb726d48Sopenharmony_ci      thread = this.works[Math.floor(Math.random() * this.works.length)];
382fb726d48Sopenharmony_ci      thread.queryFunc(name, sql, args, handler, action);
383fb726d48Sopenharmony_ci    }
384fb726d48Sopenharmony_ci  }
385fb726d48Sopenharmony_ci
386fb726d48Sopenharmony_ci  //@ts-ignore
387fb726d48Sopenharmony_ci  submitProto(name: number, args: unknow, handler: Function): void {
388fb726d48Sopenharmony_ci    let noBusyThreads = this.works.filter((it) => !it.busy);
389fb726d48Sopenharmony_ci    let thread: DbThread;
390fb726d48Sopenharmony_ci    if (noBusyThreads.length > 0) {
391fb726d48Sopenharmony_ci      //取第一个空闲的线程进行任务
392fb726d48Sopenharmony_ci      thread = noBusyThreads[0];
393fb726d48Sopenharmony_ci      thread.queryProto(name, args, handler);
394fb726d48Sopenharmony_ci    } else {
395fb726d48Sopenharmony_ci      // 随机插入一个线程中
396fb726d48Sopenharmony_ci      thread = this.works[Math.floor(Math.random() * this.works.length)];
397fb726d48Sopenharmony_ci      if (thread) {
398fb726d48Sopenharmony_ci        thread.queryProto(name, args, handler);
399fb726d48Sopenharmony_ci      }
400fb726d48Sopenharmony_ci    }
401fb726d48Sopenharmony_ci  }
402fb726d48Sopenharmony_ci
403fb726d48Sopenharmony_ci  cutFile(
404fb726d48Sopenharmony_ci    leftTs: number,
405fb726d48Sopenharmony_ci    rightTs: number,
406fb726d48Sopenharmony_ci    handler: (status: boolean, msg: string, splitBuffer?: ArrayBuffer) => void
407fb726d48Sopenharmony_ci  ): void {
408fb726d48Sopenharmony_ci    let noBusyThreads = this.works.filter((it) => !it.busy);
409fb726d48Sopenharmony_ci    let thread: DbThread;
410fb726d48Sopenharmony_ci    if (noBusyThreads.length > 0) {
411fb726d48Sopenharmony_ci      thread = noBusyThreads[0];
412fb726d48Sopenharmony_ci      thread.cutFileByRange(leftTs, rightTs, handler);
413fb726d48Sopenharmony_ci    } else {
414fb726d48Sopenharmony_ci      thread = this.works[Math.floor(Math.random() * this.works.length)];
415fb726d48Sopenharmony_ci      thread.cutFileByRange(leftTs, rightTs, handler);
416fb726d48Sopenharmony_ci    }
417fb726d48Sopenharmony_ci  }
418fb726d48Sopenharmony_ci
419fb726d48Sopenharmony_ci  progressTimer(num: number, progress: Function): void {
420fb726d48Sopenharmony_ci    let currentNum = num;
421fb726d48Sopenharmony_ci    //@ts-ignore
422fb726d48Sopenharmony_ci    clearInterval(this.cutDownTimer);
423fb726d48Sopenharmony_ci    this.cutDownTimer = setInterval(() => {
424fb726d48Sopenharmony_ci      currentNum += Math.floor(Math.random() * 3);
425fb726d48Sopenharmony_ci      if (currentNum >= 50) {
426fb726d48Sopenharmony_ci        progress('database opened', 40);
427fb726d48Sopenharmony_ci        //@ts-ignore
428fb726d48Sopenharmony_ci        clearInterval(this.cutDownTimer);
429fb726d48Sopenharmony_ci      } else {
430fb726d48Sopenharmony_ci        progress('database opened', currentNum);
431fb726d48Sopenharmony_ci      }
432fb726d48Sopenharmony_ci    }, Math.floor(Math.random() * 2500 + 1000));
433fb726d48Sopenharmony_ci  }
434fb726d48Sopenharmony_ci}
435fb726d48Sopenharmony_ci
436fb726d48Sopenharmony_ciexport const threadPool = new DbPool('1');
437fb726d48Sopenharmony_ciexport const threadPool2 = new DbPool('2');
438fb726d48Sopenharmony_ci
439fb726d48Sopenharmony_ciexport interface ThreadPoolConfig {
440fb726d48Sopenharmony_ci  action?: string | null,
441fb726d48Sopenharmony_ci  traceId?: string | null | undefined
442fb726d48Sopenharmony_ci}
443fb726d48Sopenharmony_ci
444fb726d48Sopenharmony_ciexport function getThreadPool(traceId?: string | null): DbPool {
445fb726d48Sopenharmony_ci  return traceId === '2' ? threadPool2 : threadPool;
446fb726d48Sopenharmony_ci}
447fb726d48Sopenharmony_ci
448fb726d48Sopenharmony_ciexport function query<T>(
449fb726d48Sopenharmony_ci  name: string,
450fb726d48Sopenharmony_ci  sql: string,
451fb726d48Sopenharmony_ci  args: unknown = null,
452fb726d48Sopenharmony_ci  config?: ThreadPoolConfig
453fb726d48Sopenharmony_ci): Promise<Array<T>> {
454fb726d48Sopenharmony_ci  return new Promise<Array<T>>((resolve, reject): void => {
455fb726d48Sopenharmony_ci    getThreadPool(config?.traceId).submit(
456fb726d48Sopenharmony_ci      name,
457fb726d48Sopenharmony_ci      sql,
458fb726d48Sopenharmony_ci      args,
459fb726d48Sopenharmony_ci      (res: Array<T>) => {
460fb726d48Sopenharmony_ci        if (res[0] && res[0] === 'error') {
461fb726d48Sopenharmony_ci          window.publish(window.SmartEvent.UI.Error, res[1]);
462fb726d48Sopenharmony_ci          reject(res);
463fb726d48Sopenharmony_ci        } else {
464fb726d48Sopenharmony_ci          resolve(res);
465fb726d48Sopenharmony_ci        }
466fb726d48Sopenharmony_ci      },
467fb726d48Sopenharmony_ci      config ? (config.action || null) : null
468fb726d48Sopenharmony_ci    );
469fb726d48Sopenharmony_ci  });
470fb726d48Sopenharmony_ci}
471fb726d48Sopenharmony_ci
472fb726d48Sopenharmony_ciexport function setThreadPoolTraceBuffer(traceId: string, buf: ArrayBuffer | null): void {
473fb726d48Sopenharmony_ci  if (traceId === threadPool2.traceId) {
474fb726d48Sopenharmony_ci    threadPool2.sharedBuffer = buf;
475fb726d48Sopenharmony_ci  } else {
476fb726d48Sopenharmony_ci    threadPool.sharedBuffer = buf;
477fb726d48Sopenharmony_ci  }
478fb726d48Sopenharmony_ci}
479fb726d48Sopenharmony_ci
480fb726d48Sopenharmony_ciexport function getThreadPoolTraceBuffer(traceId: string): ArrayBuffer | null {
481fb726d48Sopenharmony_ci  return traceId === threadPool2.traceId ? threadPool2.sharedBuffer : threadPool.sharedBuffer;
482fb726d48Sopenharmony_ci}
483fb726d48Sopenharmony_ci
484fb726d48Sopenharmony_ciexport function setThreadPoolTraceBufferCacheKey(traceId: string, key: string): void {
485fb726d48Sopenharmony_ci  if (traceId === threadPool2.traceId) {
486fb726d48Sopenharmony_ci    threadPool2.fileCacheKey = key;
487fb726d48Sopenharmony_ci  } else {
488fb726d48Sopenharmony_ci    threadPool.fileCacheKey = key;
489fb726d48Sopenharmony_ci  }
490fb726d48Sopenharmony_ci}
491fb726d48Sopenharmony_ci
492fb726d48Sopenharmony_ciexport function getThreadPoolTraceBufferCacheKey(traceId: string): string {
493fb726d48Sopenharmony_ci  return traceId === threadPool2.traceId ? threadPool2.fileCacheKey : threadPool.fileCacheKey;
494fb726d48Sopenharmony_ci}
495