From 02d15a7ebd73a26e7d2b87f2a6c978170778ffcc Mon Sep 17 00:00:00 2001 From: stephan Date: Mon, 31 Oct 2022 13:50:05 +0000 Subject: [PATCH] Worker1: use a list, rather than a single slot, to manage the default db link so that we can keep the least-recently-opened db as the default. Re-introduce worker1.export() but do not yet expose it until an equivalent import() (or open() option) is implemented. FossilOrigin-Name: c7750c101d9b7baa31496731bc34ea0a9b2bad0c11e2b3e92a8c7b327135c1bb --- ext/wasm/api/sqlite3-api-glue.js | 10 ++++- ext/wasm/api/sqlite3-api-worker1.js | 59 ++++++++++++++--------------- manifest | 14 +++---- manifest.uuid | 2 +- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js index 63425e538c..1477af7598 100644 --- a/ext/wasm/api/sqlite3-api-glue.js +++ b/ext/wasm/api/sqlite3-api-glue.js @@ -634,7 +634,13 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const kvvfsStorage = (zClass)=> ((115/*=='s'*/===wasm.getMemValue(zClass)) ? sessionStorage : localStorage); - + + /** + Implementations for members of the object referred to by + sqlite3_wasm_kvvfs_methods(). We swap out the native + implementations with these, which use localStorage or + sessionStorage for their backing store. + */ const kvvfsImpls = { xRead: (zClass, zKey, zBuf, nBuf)=>{ const stack = pstack.pointer, @@ -696,7 +702,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } } }/*kvvfsImpls*/; - for(let k of Object.keys(kvvfsImpls)){ + for(const k of Object.keys(kvvfsImpls)){ kvvfsMethods[kvvfsMethods.memberKey(k)] = wasm.installFunction( kvvfsMethods.memberSignature(k), diff --git a/ext/wasm/api/sqlite3-api-worker1.js b/ext/wasm/api/sqlite3-api-worker1.js index 1e8048159e..aa438a52dc 100644 --- a/ext/wasm/api/sqlite3-api-worker1.js +++ b/ext/wasm/api/sqlite3-api-worker1.js @@ -204,9 +204,10 @@ dbId: an opaque ID value which must be passed in the message envelope to other calls in this API to tell them which db to use. If it is not provided to future calls, they will default to - operating on the first-opened db. This property is, for API - consistency's sake, also part of the containing message envelope. - Only the `open` operation includes it in the `result` property. + operating on the least-recently-opened db. This property is, for + API consistency's sake, also part of the containing message + envelope. Only the `open` operation includes it in the `result` + property. persistent: true if the given filename resides in the known-persistent storage, else false. @@ -348,9 +349,12 @@ sqlite3.initWorker1API = function(){ Internal helper for managing Worker-level state. */ const wState = { - /** First-opened db is the default for future operations when no - dbId is provided by the client. */ - defaultDb: undefined, + /** + Each opened DB is added to this.dbList, and the first entry in + that list is the default db. As each db is closed, its entry is + removed from the list. + */ + dbList: [], /** Sequence number of dbId generation. */ idSeq: 0, /** Map of DB instances to dbId. */ @@ -360,7 +364,7 @@ sqlite3.initWorker1API = function(){ open: function(opt){ const db = new DB(opt.filename); this.dbs[getDbId(db)] = db; - if(!this.defaultDb) this.defaultDb = db; + if(this.dbList.indexOf(db)<0) this.dbList.push(db); return db; }, close: function(db,alsoUnlink){ @@ -369,7 +373,8 @@ sqlite3.initWorker1API = function(){ const filename = db.filename; const pVfs = sqlite3.wasm.sqlite3_wasm_db_vfs(db.pointer, 0); db.close(); - if(db===this.defaultDb) this.defaultDb = undefined; + const ddNdx = this.dbList.indexOf(db); + if(ddNdx>=0) this.dbList.splice(ddNdx, 1); if(alsoUnlink && filename && pVfs){ sqlite3.wasm.sqlite3_wasm_vfs_unlink(pVfs, filename); } @@ -399,24 +404,25 @@ sqlite3.initWorker1API = function(){ } }; - /** Throws if the given db is falsy or not opened. */ - const affirmDbOpen = function(db = wState.defaultDb){ + /** Throws if the given db is falsy or not opened, else returns its + argument. */ + const affirmDbOpen = function(db = wState.dbList[0]){ return (db && db.pointer) ? db : toss("DB is not opened."); }; /** Extract dbId from the given message payload. */ const getMsgDb = function(msgData,affirmExists=true){ - const db = wState.getDb(msgData.dbId,false) || wState.defaultDb; + const db = wState.getDb(msgData.dbId,false) || wState.dbList[0]; return affirmExists ? affirmDbOpen(db) : db; }; const getDefaultDbId = function(){ - return wState.defaultDb && getDbId(wState.defaultDb); + return wState.dbList[0] && getDbId(wState.dbList[0]); }; /** - A level of "organizational abstraction" for the Worker - API. Each method in this object must map directly to a Worker + A level of "organizational abstraction" for the Worker1 + API. Each method in this object must map directly to a Worker1 message type key. The onmessage() dispatcher attempts to dispatch all inbound messages to a method of this object, passing it the event.data part of the inbound event object. All @@ -440,7 +446,7 @@ sqlite3.initWorker1API = function(){ const db = wState.open(oargs); rc.filename = db.filename; rc.persistent = (!!pDir && db.filename.startsWith(pDir+'/')) - || sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs"); + || !!sqlite3.capi.sqlite3_js_db_uses_vfs(db.pointer, "opfs"); rc.dbId = getDbId(db); return rc; }, @@ -526,38 +532,29 @@ sqlite3.initWorker1API = function(){ }, /** - TO(RE)DO, once we can abstract away access to the - JS environment's virtual filesystem. Currently this - always throws. - - Response is (should be) an object: + Exports the database to a byte array, as per + sqlite3_serialize(). Response is an object: { - buffer: Uint8Array (db file contents), + bytearray: Uint8Array (db file contents), filename: the current db filename, mimetype: 'application/x-sqlite3' } - - 2022-09-30: we have shell.c:fiddle_export_db() which works fine - for disk-based databases (even if it's a virtual disk like an - Emscripten VFS). sqlite3_serialize() can return this for - :memory: and temp databases. */ export: function(ev){ - toss("export() requires reimplementing for portability reasons."); /** We need to reimplement this to use the Emscripten FS interface. That part used to be in the OO#1 API but that dependency was removed from that level of the API. */ - /**const db = getMsgDb(ev); + const db = getMsgDb(ev); const response = { - buffer: db.exportBinaryImage(), + bytearray: sqlite3.capi.sqlite3_js_db_export(db.pointer), filename: db.filename, mimetype: 'application/x-sqlite3' }; - wState.xfer.push(response.buffer.buffer); - return response;**/ + wState.xfer.push(response.bytearray.buffer); + return response; }/*export()*/, toss: function(ev){ diff --git a/manifest b/manifest index 022d02a5b3..de9c7c6178 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Internal\stweaks\sto\sthe\sOPFS\sVFS\sresult\scodes. -D 2022-10-31T11:53:34.287 +C Worker1:\suse\sa\slist,\srather\sthan\sa\ssingle\sslot,\sto\smanage\sthe\sdefault\sdb\slink\sso\sthat\swe\scan\skeep\sthe\sleast-recently-opened\sdb\sas\sthe\sdefault.\sRe-introduce\sworker1.export()\sbut\sdo\snot\syet\sexpose\sit\suntil\san\sequivalent\simport()\s(or\sopen()\soption)\sis\simplemented. +D 2022-10-31T13:50:05.655 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -499,11 +499,11 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08 F ext/wasm/api/post-js-header.js d6ab3dfef4a06960d28a7eaa338d4e2a1a5981e9b38718168bbde8fdb2a439b8 F ext/wasm/api/pre-js.js 287e462f969342b032c03900e668099fa1471d852df7a472de5bc349161d9c04 F ext/wasm/api/sqlite3-api-cleanup.js ecdc69dbfccfe26146f04799fcfd4a6f5790d46e7e3b9b6e9b0491f92ed8ae34 -F ext/wasm/api/sqlite3-api-glue.js b87543534821ecfa56fc0d0cd153a115fa974e70d6217964baf6e93ef8d25fb1 +F ext/wasm/api/sqlite3-api-glue.js ebfd1d01b249c705482bfe3bdef3b1feaecf55821c46abf79b8105ec9b1c2b1a F ext/wasm/api/sqlite3-api-oo1.js 4028bc2bac7e3ae2d23b7c99828155b4a06da006b51dc2a929bc0db26337370d F ext/wasm/api/sqlite3-api-opfs.js 6880cc79a4d1b6075942298d9d1ab07e24d81fbd9e5fe6b7c797b86e4b2af596 F ext/wasm/api/sqlite3-api-prologue.js 873986ca150c79510f647b910f8349bc71b14db21e444cab3b9fad9c4f39ffc7 -F ext/wasm/api/sqlite3-api-worker1.js efdca1b42299d80b54f366d15a8fc5343f3b3e9e3647e5c1fd6f3ee1015e501b +F ext/wasm/api/sqlite3-api-worker1.js 7de5160ba86ed216e8b99ba1ae0c39c1ff85c11a4818252bfc8dd0dc21109b84 F ext/wasm/api/sqlite3-license-version-header.js a661182fc93fc2cf212dfd0b987f8e138a3ac98f850b1112e29b5fbdaecc87c3 F ext/wasm/api/sqlite3-opfs-async-proxy.js b2264efef84c4a0af5dab426d7573d8b4ee5af3a25ba108b709a835a613c5e36 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 @@ -2054,8 +2054,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 69d36a6aa5e2cd79d26c0fd3e0d20fe8838fd1be97db07725233bfff1dfe6643 -R a5a69989c955a2bef03fc5f6b9426b6e +P 32e1a2d2eb8738ae1635e413829f6cf7f64c63d2a86b72940a573de89948e529 +R be757150eb7a7434baec9e7c2d1f82d1 U stephan -Z 2e8ea5a9464277cec17ca6c43e6fd2fa +Z e060f282e47bf79484c50e0b31025d45 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 2c99a664e4..15cf0e3aad 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -32e1a2d2eb8738ae1635e413829f6cf7f64c63d2a86b72940a573de89948e529 \ No newline at end of file +c7750c101d9b7baa31496731bc34ea0a9b2bad0c11e2b3e92a8c7b327135c1bb \ No newline at end of file