From: stephan Date: Wed, 19 Jul 2023 17:47:02 +0000 (+0000) Subject: More internal refactoring and docs for opfs-sahpool. X-Git-Tag: version-3.43.0~122^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=55f318e53f0dc9343b2bc87956a3ea263e06eba3;p=thirdparty%2Fsqlite.git More internal refactoring and docs for opfs-sahpool. FossilOrigin-Name: 64ccf6177a019eab46fb3345ad1e8ba80eaf2c9da55767031f9f04ccd16afb4d --- diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js index b0d71c50ee..f34c87004d 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js +++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.js @@ -48,8 +48,9 @@ incompatible with that VFS. - This VFS requires the "semi-fully-sync" FileSystemSyncAccessHandle - (hereafter "SAH") APIs released with Chrome v108. If that API - is not detected, the VFS is not registered. + (hereafter "SAH") APIs released with Chrome v108 (and all other + major browsers released since March 2023). If that API is not + detected, the VFS is not registered. */ 'use strict'; globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ @@ -137,11 +138,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xClose: function(pFile){ const pool = getPoolForPFile(pFile); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); if(file) { try{ pool.log(`xClose ${file.path}`); - pool.setFileForPtr(pFile, false); + pool.mapSFileToOFile(pFile, false); file.sah.flush(); if(file.flags & capi.SQLITE_OPEN_DELETEONCLOSE){ pool.deletePath(file.path); @@ -162,7 +163,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xFileSize: function(pFile,pSz64){ const pool = getPoolForPFile(pFile); pool.log(`xFileSize`); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); const size = file.sah.getSize() - HEADER_OFFSET_DATA; //log(`xFileSize ${file.path} ${size}`); wasm.poke64(pSz64, BigInt(size)); @@ -172,14 +173,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log(`xLock ${lockType}`); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); file.lockType = lockType; return 0; }, xRead: function(pFile,pDest,n,offset64){ const pool = getPoolForPFile(pFile); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); pool.log(`xRead ${file.path} ${n} @ ${offset64}`); try { const nRead = file.sah.read( @@ -203,7 +204,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log(`xSync ${flags}`); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); //log(`xSync ${file.path} ${flags}`); try{ file.sah.flush(); @@ -217,7 +218,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const pool = getPoolForPFile(pFile); pool.log(`xTruncate ${sz64}`); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); //log(`xTruncate ${file.path} ${iSize}`); try{ file.sah.truncate(HEADER_OFFSET_DATA + Number(sz64)); @@ -230,14 +231,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ xUnlock: function(pFile,lockType){ const pool = getPoolForPFile(pFile); pool.log('xUnlock'); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); file.lockType = lockType; return 0; }, xWrite: function(pFile,pSrc,n,offset64){ const pool = getPoolForPFile(pFile); pool.storeErr(); - const file = pool.getFileForPtr(pFile); + const file = pool.getOFileForSFile(pFile); pool.log(`xWrite ${file.path} ${n} ${offset64}`); try{ const nBytes = file.sah.write( @@ -349,7 +350,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ // Subsequent I/O methods are only passed the sqlite3_file // pointer, so map the relevant info we need to that pointer. const file = {path, flags, sah}; - pool.setFileForPtr(pFile, file); + pool.mapSFileToOFile(pFile, file); file.lockType = capi.SQLITE_LOCK_NONE; const sq3File = new capi.sqlite3_file(pFile); sq3File.$pMethods = opfsIoMethods.pointer; @@ -436,6 +437,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /** Buffer used by [sg]etAssociatedPath(). */ #apBody = new Uint8Array(HEADER_CORPUS_SIZE); + // DataView for this.#apBody #dvBody; // associated sqlite3_vfs instance @@ -497,6 +499,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return this.getCapacity(); } + /** + Reduce capacity by n, but can only reduce up to the limit + of currently-available SAHs. Returns a Promise which resolves + to the number of slots really removed. + */ async reduceCapacity(n){ let nRm = 0; for(const ah of Array.from(this.#availableSAH)){ @@ -514,7 +521,8 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } /** - Releases all currently-opened SAHs. + Releases all currently-opened SAHs. The only legal + operation after this is acquireAccessHandles(). */ releaseAccessHandles(){ for(const ah of this.#mapSAHToName.keys()) ah.close(); @@ -637,8 +645,11 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } /** - Computes a digest for the given byte array and - returns it as a two-element Uint32Array. + Computes a digest for the given byte array and returns it as a + two-element Uint32Array. This digest gets stored in the + metadata for each file as a validation check. Changing this + algorithm invalidates all existing databases for this VFS, so + don't do that. */ computeDigest(byteArray){ let h1 = 0xdeadbeef; @@ -730,14 +741,18 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return rc; } - getFileForPtr(ptr){ + /** + Given an (sqlite3_file*), returns the mapped + xOpen file object. + */ + getOFileForSFile(ptr){ return this.#mapSqlite3FileToFile.get(ptr); } /** Maps or unmaps (if file is falsy) the given (sqlite3_file*) to an xOpen file object and to this pool object. */ - setFileForPtr(pFile,file){ + mapSFileToOFile(pFile,file){ if(file){ this.#mapSqlite3FileToFile.set(pFile, file); setPoolForPFile(pFile, this); @@ -746,14 +761,34 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ setPoolForPFile(pFile, false); } } + + /** + Returns true if the given client-defined file name is in this + object's name-to-SAH map. + */ hasFilename(name){ return this.#mapFilenameToSAH.has(name) } + /** + Returns the SAH associated with the given + client-defined file name. + */ getSAHForPath(path){ return this.#mapFilenameToSAH.get(path); } + /** + Removes this object's sqlite3_vfs registration and shuts down + this object, releasing all handles, mappings, and whatnot, + including deleting its data directory. There is currently no + way to "revive" the object and reaquire its resources. + + This function is intended primarily for testing. + + Resolves to true if it did its job, false if the + VFS has already been shut down. + */ async removeVfs(){ if(!this.#cVfs.pointer) return false; capi.sqlite3_vfs_unregister(this.#cVfs.pointer); @@ -773,6 +808,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return true; } + //! Documented elsewhere in this file. exportFile(name){ const sah = this.#mapFilenameToSAH.get(name) || toss("File not found:",name); const n = sah.getSize() - HEADER_OFFSET_DATA; @@ -781,6 +817,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return b; } + //! Documented elsewhere in this file. importDb(name, bytes){ const n = bytes.byteLength; if(n<512 || n%512!=0){ @@ -803,13 +840,15 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /** - A SAHPoolUtil instance is exposed to clients in order to manipulate an OpfsSAHPool object without directly exposing that + A OpfsSAHPoolUtil instance is exposed to clients in order to + manipulate an OpfsSAHPool object without directly exposing that object and allowing for some semantic changes compared to that class. - Class docs are in the client-level docs for installOpfsSAHPoolVfs(). + Class docs are in the client-level docs for + installOpfsSAHPoolVfs(). */ - class SAHPoolUtil { + class OpfsSAHPoolUtil { /* This object's associated OpfsSAHPool. */ #p; @@ -818,18 +857,14 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ this.vfsName = sahPool.vfsName; } - async addCapacity(n){ - return this.#p.addCapacity(n); - } - async reduceCapacity(n){ - return this.#p.reduceCapacity(n); - } - getCapacity(){ - return this.#p.getCapacity(this.#p); - } - getFileCount(){ - return this.#p.getFileCount(); - } + async addCapacity(n){ return this.#p.addCapacity(n) } + + async reduceCapacity(n){ return this.#p.reduceCapacity(n) } + + getCapacity(){ return this.#p.getCapacity(this.#p) } + + getFileCount(){ return this.#p.getFileCount() } + async reserveMinimumCapacity(min){ const c = this.#p.getCapacity(); return (c < min) ? this.#p.addCapacity(min - c) : c; @@ -839,20 +874,17 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ importDb(name, bytes){ return this.#p.importDb(name,bytes) } - async wipeFiles(){return this.#p.reset(true)} + async wipeFiles(){ return this.#p.reset(true) } - unlink(filename){ - return this.#p.deletePath(filename); - } + unlink(filename){ return this.#p.deletePath(filename) } - async removeVfs(){return this.#p.removeVfs()} + async removeVfs(){ return this.#p.removeVfs() } - }/* class SAHPoolUtil */; + }/* class OpfsSAHPoolUtil */; /** - Ensure that the client has a "fully-sync" SAH impl, - else reject the promise. Returns true on success, - throws on error. + Returns a resolved Promise if the current environment + has a "fully-sync" SAH impl, else a rejected Promise. */ const apiVersionCheck = async ()=>{ const dh = await navigator.storage.getDirectory(); @@ -1087,7 +1119,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ return thePool.isReady.then(async()=>{ /** The poolUtil object will be the result of the resolved Promise. */ - const poolUtil = new SAHPoolUtil(thePool); + const poolUtil = new OpfsSAHPoolUtil(thePool); if(sqlite3.oo1){ const oo1 = sqlite3.oo1; diff --git a/manifest b/manifest index 46c9678ff8..9bf3bd22cd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\sdevelopment-over-ssh\sdocs\sfor\sthe\swasm\sbuild. -D 2023-07-19T17:46:28.936 +C More\sinternal\srefactoring\sand\sdocs\sfor\sopfs-sahpool. +D 2023-07-19T17:47:02.768 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -502,7 +502,7 @@ F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b17386 F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379 F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25 -F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js d3e41757230c8a41fccc4db077d029546f0ebccd13d4ba0111c52ca77779ab70 +F ext/wasm/api/sqlite3-vfs-opfs-sahpool.js 05b5646b91faa947833d43a840e8b94abb441afa953ee5a11cc7f07f4e01361a F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 4946af0d6fbd395aa39966562ca85900664605a5f0cc10fff50146dee527812c F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 534481cd0c2e6f62dd0a82f25d4b78fdcc671eb70d6966693c98212a6420891c -R 3098985ac29097adbc0d24d2b5daf2dc +P 500109bd0a4c134b91c37f397ff1ee828e09c17f7ecd153f975ede748caee7bb +R 44dc85544ec440f7c21f7b899d57ed02 U stephan -Z 78455e14df71dd2dbc1be007d9b53932 +Z e1c9bd04ae7a0c44d52816708800bbbb # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 7bb3f99cae..d4e846dedc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -500109bd0a4c134b91c37f397ff1ee828e09c17f7ecd153f975ede748caee7bb \ No newline at end of file +64ccf6177a019eab46fb3345ad1e8ba80eaf2c9da55767031f9f04ccd16afb4d \ No newline at end of file