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_ciimport { info } from '../../log/Log';
16fb726d48Sopenharmony_ci
17fb726d48Sopenharmony_ci/**
18fb726d48Sopenharmony_ci * 数据缓存期限
19fb726d48Sopenharmony_ci */
20fb726d48Sopenharmony_ciconst file_cache_due = 24 * 60 * 60 * 1000;
21fb726d48Sopenharmony_ciconst db_version = 6;
22fb726d48Sopenharmony_ci/**
23fb726d48Sopenharmony_ci * 初始化indexed db
24fb726d48Sopenharmony_ci */
25fb726d48Sopenharmony_ciexport function initIndexedDB(): Promise<IDBDatabase> {
26fb726d48Sopenharmony_ci  return new Promise((resolve, reject) => {
27fb726d48Sopenharmony_ci    let request = indexedDB.open('smart_perf', db_version);
28fb726d48Sopenharmony_ci    request.onerror = function (event): void {};
29fb726d48Sopenharmony_ci    request.onsuccess = function (event): void {
30fb726d48Sopenharmony_ci      let db = request.result;
31fb726d48Sopenharmony_ci      resolve(db);
32fb726d48Sopenharmony_ci    };
33fb726d48Sopenharmony_ci    request.onupgradeneeded = function (event): void {
34fb726d48Sopenharmony_ci      // @ts-ignore
35fb726d48Sopenharmony_ci      let db = event!.target!.result;
36fb726d48Sopenharmony_ci      if (db.objectStoreNames.contains('trace_file')) {
37fb726d48Sopenharmony_ci        info('delete trace_file table');
38fb726d48Sopenharmony_ci        db.deleteObjectStore('trace_file');
39fb726d48Sopenharmony_ci      }
40fb726d48Sopenharmony_ci      info('create trace_file table');
41fb726d48Sopenharmony_ci      let objectStore = db.createObjectStore('trace_file', { keyPath: 'file_index' });
42fb726d48Sopenharmony_ci      objectStore.createIndex('file_no', 'file_no');
43fb726d48Sopenharmony_ci      objectStore.createIndex('file_id', 'file_id');
44fb726d48Sopenharmony_ci      objectStore.createIndex('file_time', 'file_time');
45fb726d48Sopenharmony_ci      objectStore.createIndex('file_buffer', 'file_buffer');
46fb726d48Sopenharmony_ci    };
47fb726d48Sopenharmony_ci  });
48fb726d48Sopenharmony_ci}
49fb726d48Sopenharmony_ci
50fb726d48Sopenharmony_ci/**
51fb726d48Sopenharmony_ci * 删除过期数据
52fb726d48Sopenharmony_ci * @param db
53fb726d48Sopenharmony_ci */
54fb726d48Sopenharmony_ciexport function deleteExpireData(db: IDBDatabase): void {
55fb726d48Sopenharmony_ci  if (db?.objectStoreNames.contains('trace_file')) {
56fb726d48Sopenharmony_ci    let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
57fb726d48Sopenharmony_ci    let request = objectStore.getAll();
58fb726d48Sopenharmony_ci    request.onsuccess = function (event): void {
59fb726d48Sopenharmony_ci      let now = new Date().getTime();
60fb726d48Sopenharmony_ci      for (let re of request.result) {
61fb726d48Sopenharmony_ci        if (now - re.file_time > file_cache_due) {
62fb726d48Sopenharmony_ci          objectStore.delete(re.file_index);
63fb726d48Sopenharmony_ci        }
64fb726d48Sopenharmony_ci      }
65fb726d48Sopenharmony_ci      db.close();
66fb726d48Sopenharmony_ci    };
67fb726d48Sopenharmony_ci    request.onerror = function (): void {
68fb726d48Sopenharmony_ci      info('delete expire data failed');
69fb726d48Sopenharmony_ci    };
70fb726d48Sopenharmony_ci  }
71fb726d48Sopenharmony_ci}
72fb726d48Sopenharmony_ci
73fb726d48Sopenharmony_ci/**
74fb726d48Sopenharmony_ci * 缓存数据
75fb726d48Sopenharmony_ci * @param db 数据库链接对象
76fb726d48Sopenharmony_ci * @param oldFileId 上次打开的文件id
77fb726d48Sopenharmony_ci * @param fileId 当前打开的文件id
78fb726d48Sopenharmony_ci * @param buffer 二进制数据
79fb726d48Sopenharmony_ci */
80fb726d48Sopenharmony_ciexport function cacheTraceFileBuffer(db: IDBDatabase, oldFileId: string, fileId: string, buffer: ArrayBuffer): void {
81fb726d48Sopenharmony_ci  if (db?.objectStoreNames.contains('trace_file')) {
82fb726d48Sopenharmony_ci    let objectStore = db.transaction(['trace_file'], 'readwrite').objectStore('trace_file');
83fb726d48Sopenharmony_ci    let request = objectStore.index('file_id').getAll(oldFileId);
84fb726d48Sopenharmony_ci    request.onsuccess = function (event): void {
85fb726d48Sopenharmony_ci      for (let re of request.result) {
86fb726d48Sopenharmony_ci        objectStore.delete(re.file_index);
87fb726d48Sopenharmony_ci      }
88fb726d48Sopenharmony_ci      info('delete file success');
89fb726d48Sopenharmony_ci      let size = buffer.byteLength;
90fb726d48Sopenharmony_ci      let index = 0;
91fb726d48Sopenharmony_ci      let no = 0;
92fb726d48Sopenharmony_ci      let time = new Date().getTime();
93fb726d48Sopenharmony_ci      while (index < size) {
94fb726d48Sopenharmony_ci        let sliceLen = Math.min(size - index, 4 * 1024 * 1024);
95fb726d48Sopenharmony_ci        objectStore.add({
96fb726d48Sopenharmony_ci          file_index: randomUUID(),
97fb726d48Sopenharmony_ci          file_no: no,
98fb726d48Sopenharmony_ci          file_id: fileId,
99fb726d48Sopenharmony_ci          file_time: time,
100fb726d48Sopenharmony_ci          file_buffer: buffer.slice(index, index + sliceLen),
101fb726d48Sopenharmony_ci        });
102fb726d48Sopenharmony_ci        no++;
103fb726d48Sopenharmony_ci        index += sliceLen;
104fb726d48Sopenharmony_ci      }
105fb726d48Sopenharmony_ci      info('cache file success', fileId, buffer.byteLength);
106fb726d48Sopenharmony_ci      db.close();
107fb726d48Sopenharmony_ci    };
108fb726d48Sopenharmony_ci    request.onerror = function (ev): void {
109fb726d48Sopenharmony_ci      info('delete error', fileId);
110fb726d48Sopenharmony_ci    };
111fb726d48Sopenharmony_ci  }
112fb726d48Sopenharmony_ci}
113fb726d48Sopenharmony_ci
114fb726d48Sopenharmony_cifunction randomUUID(): string {
115fb726d48Sopenharmony_ci  // @ts-ignore
116fb726d48Sopenharmony_ci  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c: unknown) =>
117fb726d48Sopenharmony_ci    //@ts-ignore
118fb726d48Sopenharmony_ci    (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
119fb726d48Sopenharmony_ci  );
120fb726d48Sopenharmony_ci}
121fb726d48Sopenharmony_ci
122fb726d48Sopenharmony_ci/**
123fb726d48Sopenharmony_ci * 获取当前文件的 二进制数据
124fb726d48Sopenharmony_ci * @param fileId
125fb726d48Sopenharmony_ci */
126fb726d48Sopenharmony_ciexport function getTraceFileBuffer(fileId: string): Promise<ArrayBuffer | null> {
127fb726d48Sopenharmony_ci  return new Promise((resolve) => {
128fb726d48Sopenharmony_ci    if (fileId === null || fileId === undefined || fileId === '') {
129fb726d48Sopenharmony_ci      resolve(new Uint8Array(0).buffer);
130fb726d48Sopenharmony_ci    } else {
131fb726d48Sopenharmony_ci      initIndexedDB().then((db) => {
132fb726d48Sopenharmony_ci        if (db?.objectStoreNames.contains('trace_file')) {
133fb726d48Sopenharmony_ci          let request = db
134fb726d48Sopenharmony_ci            .transaction(['trace_file'], 'readwrite')
135fb726d48Sopenharmony_ci            .objectStore('trace_file')
136fb726d48Sopenharmony_ci            .index('file_id')
137fb726d48Sopenharmony_ci            .getAll(fileId);
138fb726d48Sopenharmony_ci          request.onsuccess = function (ev): void {
139fb726d48Sopenharmony_ci            let totalLen = 0;
140fb726d48Sopenharmony_ci            let arr = request.result.sort((a, b) => a.file_no - b.file_no);
141fb726d48Sopenharmony_ci            for (let re of arr) {
142fb726d48Sopenharmony_ci              totalLen += re.file_buffer.byteLength;
143fb726d48Sopenharmony_ci            }
144fb726d48Sopenharmony_ci            let buffer = new Uint8Array(totalLen);
145fb726d48Sopenharmony_ci            let offset = 0;
146fb726d48Sopenharmony_ci            for (let re of arr) {
147fb726d48Sopenharmony_ci              let ua = new Uint8Array(re.file_buffer);
148fb726d48Sopenharmony_ci              buffer.set(ua, offset);
149fb726d48Sopenharmony_ci              offset += re.file_buffer.byteLength;
150fb726d48Sopenharmony_ci            }
151fb726d48Sopenharmony_ci            arr.length = 0;
152fb726d48Sopenharmony_ci            request.result.length = 0;
153fb726d48Sopenharmony_ci            resolve(buffer.buffer);
154fb726d48Sopenharmony_ci          };
155fb726d48Sopenharmony_ci        } else {
156fb726d48Sopenharmony_ci          resolve(new Uint8Array(0).buffer);
157fb726d48Sopenharmony_ci        }
158fb726d48Sopenharmony_ci      });
159fb726d48Sopenharmony_ci    }
160fb726d48Sopenharmony_ci  });
161fb726d48Sopenharmony_ci}
162