diff --git a/binding/javascript/ReadMe.md b/binding/javascript/ReadMe.md index ce54191..53f2763 100644 --- a/binding/javascript/ReadMe.md +++ b/binding/javascript/ReadMe.md @@ -22,7 +22,7 @@ let version = IPv6; ### 文件验证 建议您主动去验证 xdb 文件的适用性,因为后期的一些新功能可能会导致目前的 Searcher 版本无法适用你使用的 xdb 文件,验证可以避免运行过程中的一些不可预测的错误。 你不需要每次都去验证,例如在服务启动的时候,或者手动调用命令验证确认版本匹配即可,不要在每次创建的 Searcher 的时候运行验证,这样会影响查询的响应速度,尤其是高并发的使用场景。 ```javascript -import verifyFomFile from './index.js'; +import verifyFromFile from './index.js'; try { verifyFromFile(dbPath); @@ -30,6 +30,7 @@ try { // 适用性验证失败!!! // 当前查询客户端实现不适用于 dbPath 指定的 xdb 文件的查询. // 应该停止启动服务,使用合适的 xdb 文件或者升级到适合 dbPath 的 Searcher 实现。 + console.log(`binding is not applicable for xdb file '${dbPath}': ${e.message}`); return; } diff --git a/binding/javascript/index.js b/binding/javascript/index.js index aa73e93..3c2f22d 100644 --- a/binding/javascript/index.js +++ b/binding/javascript/index.js @@ -30,7 +30,9 @@ export { loadVectorIndex, loadVectorIndexFromFile, loadContent, - loadContentFromFile + loadContentFromFile, + verify, + verifyFromFile } from './util.js'; export { diff --git a/binding/javascript/tests/search.test.js b/binding/javascript/tests/search.test.js index d7b7754..d5613de 100644 --- a/binding/javascript/tests/search.test.js +++ b/binding/javascript/tests/search.test.js @@ -5,7 +5,7 @@ // searcher search tester // @Author Lion -import {IPv4, IPv6, parseIP, ipToString, newWithFileOnly} from '../index.js'; +import {IPv4, IPv6, parseIP, ipToString, newWithFileOnly, verifyFromFile} from '../index.js'; import path from 'path'; import { fileURLToPath } from 'url'; @@ -16,6 +16,18 @@ const dbPath = { } test('ipv4 search test', async () => { + // verify the xdb file + // @Note: do NOT call it every time you create a searcher since this will slow + // down the search response. + // @see the verify function for details. + try { + verifyFromFile(dbPath.v4); + console.log(`xdb file '${dbPath.v4}' verified`); + } catch (e) { + console.log(`binding is not applicable for xdb file '${dbPath.v4}': ${e.message}`); + return; + } + let searcher = newWithFileOnly(IPv4, dbPath.v4); let ip_list = [ '1.0.0.0', @@ -38,6 +50,18 @@ test('ipv4 search test', async () => { }); test('ipv6 search test', async () => { + // verify the xdb file + // @Note: do NOT call it every time you create a searcher since this will slow + // down the search response. + // @see the verify function for details. + try { + verifyFromFile(dbPath.v6); + console.log(`xdb file '${dbPath.v6}' verified`); + } catch (e) { + console.log(`binding is not applicable for xdb file '${dbPath.v6}': ${e.message}`); + return; + } + let searcher = newWithFileOnly(IPv6, dbPath.v6); let ip_list = [ '2a02:26f7:c409:4001::', diff --git a/binding/javascript/util.js b/binding/javascript/util.js index 4fb7c1a..41b3c8b 100644 --- a/binding/javascript/util.js +++ b/binding/javascript/util.js @@ -373,9 +373,42 @@ export function loadContent(fd) { export function loadContentFromFile(dbPath) { const fd = fs.openSync(dbPath, "r"); const content = loadContent(fd); - fs.close(fd, function(){}); + fs.closeSync(fd); return content; } -const ipBytes = parseIP("2a02:26f7:c409:4001::"); -console.log(ipToString(ipBytes)); \ No newline at end of file +// --- + +// Verify if the current Searcher could be used to search the specified xdb file. +// Why do we need this check ? +// The future features of the xdb impl may cause the current searcher not able to work properly. +// +// @Note: You Just need to check this ONCE when the service starts +// Or use another process (eg, A command) to check once Just to confirm the suitability. +export function verify(fd) { + const header = loadHeader(fd); + + // get the runtime ptr bytes + let runtimePtrBytes = 0; + if (header.version == XdbStructure20) { + runtimePtrBytes = 4; + } else if (header.version == XdbStructure30) { + runtimePtrBytes = header.runtimePtrBytes; + } else { + throw new Error(`invalid structure version ${header.version}`); + } + + // 1, confirm the xdb file size + // to ensure that the maximum file pointer does not overflow + const maxFilePtr = (1n << BigInt(runtimePtrBytes * 8)) - 1n; + const _fileBytes = BigInt(fs.fstatSync(fd).size); + if (_fileBytes > maxFilePtr) { + throw new Error(`xdb file exceeds the maximum supported bytes: ${maxFilePtr}`); + } +} + +export function verifyFromFile(dbPath) { + const fd = fs.openSync(dbPath, "r"); + verify(fd); + fs.closeSync(fd); +} \ No newline at end of file