diff options
-rw-r--r-- | ext/wasm/api/sqlite3-api-oo1.js | 24 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-api-opfs.js | 7 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-api-prologue.js | 13 | ||||
-rw-r--r-- | ext/wasm/api/sqlite3-wasm.c | 5 | ||||
-rw-r--r-- | ext/wasm/common/SqliteTestUtil.js | 2 | ||||
-rw-r--r-- | ext/wasm/demo-123.js | 9 | ||||
-rw-r--r-- | ext/wasm/fiddle/fiddle-worker.js | 2 | ||||
-rw-r--r-- | ext/wasm/index.html | 14 | ||||
-rw-r--r-- | ext/wasm/speedtest1-wasmfs.html | 168 | ||||
-rw-r--r-- | ext/wasm/speedtest1-worker.html | 222 | ||||
-rw-r--r-- | ext/wasm/speedtest1-worker.js | 2 | ||||
-rw-r--r-- | ext/wasm/speedtest1.html | 225 | ||||
-rw-r--r-- | manifest | 34 | ||||
-rw-r--r-- | manifest.uuid | 2 |
14 files changed, 371 insertions, 358 deletions
diff --git a/ext/wasm/api/sqlite3-api-oo1.js b/ext/wasm/api/sqlite3-api-oo1.js index e0f812baa..4f7ffe1cd 100644 --- a/ext/wasm/api/sqlite3-api-oo1.js +++ b/ext/wasm/api/sqlite3-api-oo1.js @@ -495,24 +495,25 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ } }, /** - Similar to this.filename but will return a falsy value for - special names like ":memory:". Throws if the DB has been - closed. If passed an argument it then it will return the + Similar to the this.filename property but will return a falsy + value for special names like ":memory:". Throws if the DB has + been closed. If passed an argument it then it will return the filename of the ATTACHEd db with that name, else it assumes a - name of `main`. + name of `main`. The argument may be either a JS string or + a pointer to a WASM-allocated C-string. */ getFilename: function(dbName='main'){ return capi.sqlite3_db_filename(affirmDbOpen(this).pointer, dbName); }, /** Returns true if this db instance has a name which resolves to a - file. If the name is "" or ":memory:", it resolves to false. + file. If the name is "" or starts with ":", it resolves to false. Note that it is not aware of the peculiarities of URI-style names and a URI-style name for a ":memory:" db will fool it. Returns false if this db is closed. */ hasFilename: function(){ - return this.filename && ':memory'!==this.filename; + return this.filename && ':'!==this.filename[0]; }, /** Returns the name of the given 0-based db number, as documented @@ -525,9 +526,13 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ Compiles the given SQL and returns a prepared Stmt. This is the only way to create new Stmt objects. Throws on error. - The given SQL must be a string, a Uint8Array holding SQL, or a - WASM pointer to memory holding the NUL-terminated SQL string. - If the SQL contains no statements, an SQLite3Error is thrown. + The given SQL must be a string, a Uint8Array holding SQL, a + WASM pointer to memory holding the NUL-terminated SQL string, + or an array of strings. In the latter case, the array is + concatenated together, with no separators, to form the SQL + string (arrays are often a convenient way to formulate long + statements). If the SQL contains no statements, an + SQLite3Error is thrown. Design note: the C API permits empty SQL, reporting it as a 0 result code and a NULL stmt pointer. Supporting that case here @@ -541,6 +546,7 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ */ prepare: function(sql){ affirmDbOpen(this); + if(Array.isArray(sql)) sql = sql.join(''); const stack = capi.wasm.scopedAllocPush(); let ppStmt, pStmt; try{ diff --git a/ext/wasm/api/sqlite3-api-opfs.js b/ext/wasm/api/sqlite3-api-opfs.js index e28e47ab6..a346443f5 100644 --- a/ext/wasm/api/sqlite3-api-opfs.js +++ b/ext/wasm/api/sqlite3-api-opfs.js @@ -883,12 +883,15 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri) hook in to any C-side calls to sqlite3_initialize(), so we cannot add an after-initialize callback mechanism. */ - opfsUtil.reregisterVfs = (asDefault=false)=>{ + opfsUtil.registerVfs = (asDefault=false)=>{ return capi.wasm.exports.sqlite3_vfs_register( opfsVfs.pointer, asDefault ? 1 : 0 ); }; - + + //TODO to support fiddle db upload: + //opfsUtil.createFile = function(absName, content=undefined){...} + if(sqlite3.oo1){ opfsUtil.OpfsDb = function(...args){ const opt = sqlite3.oo1.dbCtorHelper.normalizeArgs(...args); diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index b5cd292fc..b2d880937 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -120,7 +120,7 @@ the `free(3)`-compatible routine for the WASM environment. Defaults to `"free"`. - - `persistentDirName`[^1]: if the environment supports persistent storage, this + - `wasmfsOpfsDir`[^1]: if the environment supports persistent storage, this directory names the "mount point" for that directory. It must be prefixed by `/` and may currently contain only a single directory-name part. Using the root directory name is not supported by any current persistent backend. @@ -157,7 +157,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( })(), allocExportName: 'malloc', deallocExportName: 'free', - persistentDirName: '/persistent' + wasmfsOpfsDir: '/opfs' }; Object.keys(configDefaults).forEach(function(k){ config[k] = Object.getOwnPropertyDescriptor(apiConfig, k) @@ -174,7 +174,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( [ // If any of these config options are functions, replace them with // the result of calling that function... - 'Module', 'exports', 'memory', 'persistentDirName' + 'Module', 'exports', 'memory', 'wasmfsOpfsDir' ].forEach((k)=>{ if('function' === typeof config[k]){ config[k] = config[k](); @@ -185,8 +185,8 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( all args with a space between each. */ const toss = (...args)=>{throw new Error(args.join(' '))}; - if(config.persistentDirName && !/^\/[^/]+$/.test(config.persistentDirName)){ - toss("config.persistentDirName must be falsy or in the form '/dir-name'."); + if(config.wasmfsOpfsDir && !/^\/[^/]+$/.test(config.wasmfsOpfsDir)){ + toss("config.wasmfsOpfsDir must be falsy or in the form '/dir-name'."); } /** @@ -727,7 +727,7 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( capi.sqlite3_web_persistent_dir = function(){ if(undefined !== __persistentDir) return __persistentDir; // If we have no OPFS, there is no persistent dir - const pdir = config.persistentDirName; + const pdir = config.wasmfsOpfsDir; if(!pdir || !self.FileSystemHandle || !self.FileSystemDirectoryHandle @@ -748,7 +748,6 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( const pVfs = sqlite3.capi.sqlite3_vfs_find("unix-none"); if(pVfs){ capi.sqlite3_vfs_register(pVfs,1); - console.warn("Installed 'unix-none' as the default sqlite3 VFS."); } return __persistentDir = pdir; }else{ diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index cf9a1a3db..8750d9b20 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -571,7 +571,7 @@ int sqlite3_wasm_vfs_unlink(const char * zName){ WASM_KEEP int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ static backend_t pOpfs = 0; - if( !zMountPoint || !*zMountPoint ) zMountPoint = "/persistent"; + if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs"; if( !pOpfs ){ pOpfs = wasmfs_create_opfs_backend(); if( pOpfs ){ @@ -595,7 +595,8 @@ int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ } #else WASM_KEEP -int sqlite3_wasm_init_wasmfs(void){ +int sqlite3_wasm_init_wasmfs(const char *zUnused){ + if(zUnused){/*unused*/} return SQLITE_NOTFOUND; } #endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */ diff --git a/ext/wasm/common/SqliteTestUtil.js b/ext/wasm/common/SqliteTestUtil.js index 779f271fb..277ab5529 100644 --- a/ext/wasm/common/SqliteTestUtil.js +++ b/ext/wasm/common/SqliteTestUtil.js @@ -221,7 +221,7 @@ sqlite3 API. */ sqlite3ApiConfig: { - persistentDirName: "/persistent" + wasmfsOpfsDir: "/opfs" }, /** Intended to be called by apps which need to call the diff --git a/ext/wasm/demo-123.js b/ext/wasm/demo-123.js index c7dc4c769..5ba1f1df7 100644 --- a/ext/wasm/demo-123.js +++ b/ext/wasm/demo-123.js @@ -44,7 +44,7 @@ oo = sqlite3.oo1/*high-level OO API*/; log("sqlite3 version",capi.sqlite3_libversion(), capi.sqlite3_sourceid()); const db = new oo.DB("/mydb.sqlite3"); - log("transient b =",db.filename); + log("transient db =",db.filename); /** Never(!) rely on garbage collection to clean up DBs and (especially) prepared statements. Always wrap their lifetimes @@ -82,7 +82,12 @@ } log("Insert using a prepared statement..."); - let q = db.prepare("insert into t(a,b) values(?,?)"); + let q = db.prepare([ + // SQL may be a string or array of strings + // (concatenated w/o separators). + "insert into t(a,b) ", + "values(?,?)" + ]); try { for( i = 100; i < 103; ++i ){ q.bind( [i, i*2] ).step(); diff --git a/ext/wasm/fiddle/fiddle-worker.js b/ext/wasm/fiddle/fiddle-worker.js index dd8291465..b0c0526f8 100644 --- a/ext/wasm/fiddle/fiddle-worker.js +++ b/ext/wasm/fiddle/fiddle-worker.js @@ -170,7 +170,7 @@ stdout("\nOPFS is available. To open a persistent db, use:\n\n", " .open file:name?vfs=opfs\n\nbut note that some", "features (e.g. upload) do not yet work with OPFS."); - S.opfs.reregisterVfs(); + S.opfs.registerVfs(); } stdout('\nEnter ".help" for usage hints.'); this.exec([ // initialization commands... diff --git a/ext/wasm/index.html b/ext/wasm/index.html index ee31306bb..20668db20 100644 --- a/ext/wasm/index.html +++ b/ext/wasm/index.html @@ -14,7 +14,7 @@ builds. All of them require that this directory have been "make"d first. The intent is that <em>this</em> page be run using:</div> - <blockquote><pre>althttpd -page index.html</pre></blockquote> + <blockquote><pre>althttpd -enable-sab -page index.html</pre></blockquote> <div>and the individual tests be started in their own tab. Warnings and Caveats: <ul class='warning'> @@ -23,9 +23,8 @@ <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a> and <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a> - headers. The default build - of <a href='https://sqlite.org/althttpd'>althttpd</a> - <em>does not</em>. + headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the + <code>-enable-sab</code> flag for that. </li> <li>Any OPFS-related pages require very recent version of Chrome or Chromium (v102 at least, possibly newer). OPFS @@ -37,9 +36,6 @@ page may depend on build-time options which are <em>off by default</em> because they currently (as of 2022-09-08) break with Worker-based pages. - <!-- Similarly, WASMFS does not work on some platforms, - e.g. Raspberry Pi 4 (for which there is no Chrome - build, so it's currently a moot point). --> </li> </ul> </div> @@ -63,9 +59,9 @@ <li>speedtest1 ports (sqlite3's primary benchmarking tool)... <ul> <li><a href='speedtest1.html'>speedtest1</a>: a main-thread WASM build of speedtest1.</li> - <li><a href='speedtest1-wasmfs.html'>speedtest1-wasmfs</a>: a variant of speedtest1 built solely for the wasmfs/opfs feature.</li> + <li><a href='speedtest1-wasmfs.html?flags=--size,25'>speedtest1-wasmfs</a>: a variant of speedtest1 built solely for the wasmfs/opfs feature.</li> <li><a href='speedtest1.html?vfs=kvvfs'>speedtest1-kvvfs</a>: speedtest1 with the kvvfs.</li> - <li><a href='speedtest1-worker.html'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li> + <li><a href='speedtest1-worker.html?size=25'>speedtest1-worker</a>: an interactive Worker-thread variant of speedtest1.</li> <li><a href='speedtest1-worker.html?vfs=opfs&size=25'>speedtest1-worker-opfs</a>: speedtest1-worker with the OPFS VFS preselected and configured for a moderate workload.</li> </ul> diff --git a/ext/wasm/speedtest1-wasmfs.html b/ext/wasm/speedtest1-wasmfs.html index 37155282c..6952fc1ee 100644 --- a/ext/wasm/speedtest1-wasmfs.html +++ b/ext/wasm/speedtest1-wasmfs.html @@ -39,115 +39,113 @@ <script src="common/SqliteTestUtil.js"></script> <script src="speedtest1-wasmfs.js"></script> <script>(function(){ - /** - If this environment contains OPFS, this function initializes it and - returns the name of the dir on which OPFS is mounted, else it returns - an empty string. - */ - const wasmfsDir = function f(wasmUtil){ - if(undefined !== f._) return f._; - const pdir = '/persistent'; - if( !self.FileSystemHandle - || !self.FileSystemDirectoryHandle - || !self.FileSystemFileHandle){ + /** + If this environment contains OPFS, this function initializes it and + returns the name of the dir on which OPFS is mounted, else it returns + an empty string. + */ + const wasmfsDir = function f(wasmUtil,dirName="/opfs"){ + if(undefined !== f._) return f._; + if( !self.FileSystemHandle + || !self.FileSystemDirectoryHandle + || !self.FileSystemFileHandle){ return f._ = ""; - } - try{ + } + try{ if(0===wasmUtil.xCallWrapped( - 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir + 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], dirName )){ - return f._ = pdir; + return f._ = dirName; }else{ - return f._ = ""; + return f._ = ""; } - }catch(e){ + }catch(e){ // sqlite3_wasm_init_wasmfs() is not available return f._ = ""; - } - }; - wasmfsDir._ = undefined; + } + }; + wasmfsDir._ = undefined; - const eOut = document.querySelector('#test-output'); - const log2 = function(cssClass,...args){ - const ln = document.createElement('div'); - if(cssClass) ln.classList.add(cssClass); - ln.append(document.createTextNode(args.join(' '))); - eOut.append(ln); - //this.e.output.lastElementChild.scrollIntoViewIfNeeded(); - }; - const logList = []; - const dumpLogList = function(){ - logList.forEach((v)=>log2('',v)); - logList.length = 0; - }; - /* can't update DOM while speedtest is running unless we run - speedtest in a worker thread. */; - const log = (...args)=>{ - console.log(...args); - logList.push(args.join(' ')); - }; - const logErr = function(...args){ - console.error(...args); - logList.push('ERROR: '+args.join(' ')); - }; + const eOut = document.querySelector('#test-output'); + const log2 = function(cssClass,...args){ + const ln = document.createElement('div'); + if(cssClass) ln.classList.add(cssClass); + ln.append(document.createTextNode(args.join(' '))); + eOut.append(ln); + //this.e.output.lastElementChild.scrollIntoViewIfNeeded(); + }; + const logList = []; + const dumpLogList = function(){ + logList.forEach((v)=>log2('',v)); + logList.length = 0; + }; + /* can't update DOM while speedtest is running unless we run + speedtest in a worker thread. */; + const log = (...args)=>{ + console.log(...args); + logList.push(args.join(' ')); + }; + const logErr = function(...args){ + console.error(...args); + logList.push('ERROR: '+args.join(' ')); + }; - const runTests = function(sqlite3){ - console.log("Module inited."); - const wasm = sqlite3.capi.wasm; - const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); - const pDir = wasmfsDir(wasm); - if(pDir) log2('',"Persistent storage:",pDir); - else{ + const runTests = function(sqlite3){ + console.log("Module inited."); + const wasm = sqlite3.capi.wasm; + const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); + const pDir = wasmfsDir(wasm); + if(pDir) log2('',"Persistent storage:",pDir); + else{ log2('error',"Expecting persistent storage in this build."); return; - } - const scope = wasm.scopedAllocPush(); - const dbFile = pDir+"/speedtest1.db"; - const urlParams = self.SqliteTestUtil.processUrlArgs(); - const argv = ["speedtest1"]; - if(urlParams.flags){ - argv.push(...(urlParams.flags.split(','))); + } + const scope = wasm.scopedAllocPush(); + const dbFile = pDir+"/speedtest1.db"; + const urlParams = new URL(self.location.href).searchParams; + const argv = ["speedtest1"]; + if(urlParams.has('flags')){ + argv.push(...(urlParams.get('flags').split(','))); let i = argv.indexOf('--vfs'); if(i>=0) argv.splice(i,2); - }else{ + }else{ argv.push( - "--singlethread", - "--nomutex", - "--nosync", - "--nomemstat" + "--singlethread", + "--nomutex", + "--nosync", + "--nomemstat" ); //"--memdb", // note that memdb trumps the filename arg - } + } - if(argv.indexOf('--memdb')>=0){ + if(argv.indexOf('--memdb')>=0){ log2('error',"WARNING: --memdb flag trumps db filename."); - } - argv.push("--big-transactions"/*important for tests 410 and 510!*/, - dbFile); - console.log("argv =",argv); - // These log messages are not emitted to the UI until after main() returns. Fixing that - // requires moving the main() call and related cleanup into a timeout handler. - if(pDir) unlink(dbFile); - log2('',"Starting native app:\n ",argv.join(' ')); - log2('',"This will take a while and the browser might warn about the runaway JS.", - "Give it time..."); - logList.length = 0; - setTimeout(function(){ + } + argv.push("--big-transactions"/*important for tests 410 and 510!*/, + dbFile); + console.log("argv =",argv); + // These log messages are not emitted to the UI until after main() returns. Fixing that + // requires moving the main() call and related cleanup into a timeout handler. + if(pDir) unlink(dbFile); + log2('',"Starting native app:\n ",argv.join(' ')); + log2('',"This will take a while and the browser might warn about the runaway JS.", + "Give it time..."); + logList.length = 0; + setTimeout(function(){ wasm.xCall('wasm_main', argv.length, wasm.scopedAllocMainArgv(argv)); wasm.scopedAllocPop(scope); if(pDir) unlink(dbFile); logList.unshift("Done running native main(). Output:"); dumpLogList(); - }, 25); - }/*runTests()*/; + }, 25); + }/*runTests()*/; - self.sqlite3TestModule.print = log; - self.sqlite3TestModule.printErr = logErr; - sqlite3Speedtest1InitModule(self.sqlite3TestModule).then(function(M){ - runTests(M.sqlite3); - }); - })(); - </script> + self.sqlite3TestModule.print = log; + self.sqlite3TestModule.printErr = logErr; + sqlite3Speedtest1InitModule(self.sqlite3TestModule).then(function(M){ + runTests(M.sqlite3); + }); +})();</script> </body> </html> diff --git a/ext/wasm/speedtest1-worker.html b/ext/wasm/speedtest1-worker.html index b1bc3aace..b5e1089b6 100644 --- a/ext/wasm/speedtest1-worker.html +++ b/ext/wasm/speedtest1-worker.html @@ -127,75 +127,75 @@ } </style> <script>(function(){ - 'use strict'; - const E = (sel)=>document.querySelector(sel); - const eOut = E('#test-output'); - const log2 = function(cssClass,...args){ + 'use strict'; + const E = (sel)=>document.querySelector(sel); + const eOut = E('#test-output'); + const log2 = function(cssClass,...args){ let ln; if(1 || cssClass){ - ln = document.createElement('div'); - if(cssClass) ln.classList.add(cssClass); - ln.append(document.createTextNode(args.join(' '))); + ln = document.createElement('div'); + if(cssClass) ln.classList.add(cssClass); + ln.append(document.createTextNode(args.join(' '))); }else{ - // This doesn't work with the "reverse order" option! - ln = document.createTextNode(args.join(' ')+'\n'); + // This doesn't work with the "reverse order" option! + ln = document.createTextNode(args.join(' ')+'\n'); } eOut.append(ln); - }; - const log = (...args)=>{ + }; + const log = (...args)=>{ //console.log(...args); log2('', ...args); - }; - const logErr = function(...args){ + }; + const logErr = function(...args){ console.error(...args); log2('error', ...args); - }; - const logWarn = function(...args){ + }; + const logWarn = function(...args){ console.warn(...args); log2('warning', ...args); - }; + }; - const spacePad = function(str,len=21){ + const spacePad = function(str,len=21){ if(str.length===len) return str; else if(str.length>len) return str.substr(0,len); const a = []; a.length = len - str.length; return str+a.join(' '); - }; - // OPTION elements seem to ignore white-space:pre, so do this the hard way... - const nbspPad = function(str,len=21){ + }; + // OPTION elements seem to ignore white-space:pre, so do this the hard way... + const nbspPad = function(str,len=21){ if(str.length===len) return str; else if(str.length>len) return str.substr(0,len); const a = []; a.length = len - str.length; return str+a.join(' '); - }; + }; - const W = new Worker("speedtest1-worker.js"+self.location.search); - const mPost = function(msgType,payload){ + const W = new Worker("speedtest1-worker.js"+self.location.search); + const mPost = function(msgType,payload){ W.postMessage({type: msgType, data: payload}); - }; + }; - const eFlags = E('#select-flags'); - const eSelectedFlags = E('#toolbar-selected-flags'); - const eLinkMainThread = E('#link-main-thread'); - const eLinkWasmfs = E('#link-wasmfs'); - const eLinkKvvfs = E('#link-kvvfs'); - const urlParams = new URL(self.location.href).searchParams; - const getSelectedFlags = ()=>{ - const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value); - [ - 'size', 'vfs' - ].forEach(function(k){ - if(urlParams.has(k)) f.push('--'+k, urlParams.get(k)); - }); - return f; - }; - const updateSelectedFlags = function(){ + const eFlags = E('#select-flags'); + const eSelectedFlags = E('#toolbar-selected-flags'); + const eLinkMainThread = E('#link-main-thread'); + const eLinkWasmfs = E('#link-wasmfs'); + const eLinkKvvfs = E('#link-kvvfs'); + const urlParams = new URL(self.location.href).searchParams; + const getSelectedFlags = ()=>{ + const f = Array.prototype.map.call(eFlags.selectedOptions, (v)=>v.value); + [ + 'size', 'vfs' + ].forEach(function(k){ + if(urlParams.has(k)) f.push('--'+k, urlParams.get(k)); + }); + return f; + }; + const updateSelectedFlags = function(){ eSelectedFlags.innerText = ''; const flags = getSelectedFlags(); flags.forEach(function(f){ - const e = document.createElement('span'); - e.innerText = f; - eSelectedFlags.appendChild(e); + const e = document.createElement('span'); + e.innerText = f; + eSelectedFlags.appendChild(e); }); const rxStripDash = /^(-+)?/; const comma = flags.join(','); @@ -205,9 +205,9 @@ eLinkWasmfs.href = 'speedtest1-wasmfs.html?flags='+comma; eLinkKvvfs.setAttribute('target', 'speedtest1-kvvfs-'+comma); eLinkKvvfs.href = 'speedtest1-kvvfs.html?flags='+comma; - }; - eFlags.addEventListener('change', updateSelectedFlags ); - { + }; + eFlags.addEventListener('change', updateSelectedFlags ); + { const flags = Object.create(null); /* TODO? Flags which require values need custom UI controls and some of them make little sense here @@ -259,111 +259,111 @@ flags["--verify"] = "Run additional verification steps."; flags["--without"] = "rowid Use WITHOUT ROWID where appropriate"; const preselectedFlags = [ - '--big-transactions', - '--singlethread' + '--big-transactions', + '--singlethread' ]; if(urlParams.has('flags')){ - preselectedFlags.push(...urlParams.get('flags').split(',')); + preselectedFlags.push(...urlParams.get('flags').split(',')); } - if('opfs'!==urlParams.get('vfs')){ - preselectedFlags.push('--memdb'); + if('opfs'!==urlParams.get('vfs')){ + preselectedFlags.push('--memdb'); } Object.keys(flags).sort().forEach(function(f){ - const opt = document.createElement('option'); - eFlags.appendChild(opt); - const lbl = nbspPad(f)+flags[f]; - //opt.innerText = lbl; - opt.innerHTML = lbl; - opt.value = f; - if(preselectedFlags.indexOf(f) >= 0) opt.selected = true; + const opt = document.createElement('option'); + eFlags.appendChild(opt); + const lbl = nbspPad(f)+flags[f]; + //opt.innerText = lbl; + opt.innerHTML = lbl; + opt.value = f; + if(preselectedFlags.indexOf(f) >= 0) opt.selected = true; }); const cbReverseLog = E('#cb-reverse-log-order'); const lblReverseLog = E('#lbl-reverse-log-order'); if(cbReverseLog.checked){ - lblReverseLog.classList.add('warning'); - eOut.classList.add('reverse'); + lblReverseLog.classList.add('warning'); + eOut.classList.add('reverse'); } cbReverseLog.addEventListener('change', function(){ - if(this.checked){ - eOut.classList.add('reverse'); - lblReverseLog.classList.add('warning'); - }else{ - eOut.classList.remove('reverse'); - lblReverseLog.classList.remove('warning'); - } + if(this.checked){ + eOut.classList.add('reverse'); + lblReverseLog.classList.add('warning'); + }else{ + eOut.classList.remove('reverse'); + lblReverseLog.classList.remove('warning'); + } }, false); updateSelectedFlags(); - } - E('#btn-output-clear').addEventListener('click', ()=>{ + } + E('#btn-output-clear').addEventListener('click', ()=>{ eOut.innerText = ''; - }); - E('#btn-reset-flags').addEventListener('click',()=>{ + }); + E('#btn-reset-flags').addEventListener('click',()=>{ eFlags.value = ''; updateSelectedFlags(); - }); - E('#btn-run').addEventListener('click',function(){ + }); + E('#btn-run').addEventListener('click',function(){ log("Running speedtest1. UI controls will be disabled until it completes."); mPost('run', getSelectedFlags()); - }); + }); - const eControls = E('#ui-controls'); - /** Update Emscripten-related UI elements while loading the module. */ - const updateLoadStatus = function f(text){ + const eControls = E('#ui-controls'); + /** Update Emscripten-related UI elements while loading the module. */ + const updateLoadStatus = function f(text){ if(!f.last){ - f.last = { text: '', step: 0 }; - const E = (cssSelector)=>document.querySelector(cssSelector); - f.ui = { - status: E('#module-status'), - progress: E('#module-progress'), - spinner: E('#module-spinner') - }; + f.last = { text: '', step: 0 }; + const E = (cssSelector)=>document.querySelector(cssSelector); + f.ui = { + status: E('#module-status'), + progress: E('#module-progress'), + spinner: E('#module-spinner') + }; } if(text === f.last.text) return; f.last.text = text; if(f.ui.progress){ - f.ui.progress.value = f.last.step; - f.ui.progress.max = f.last.step + 1; + f.ui.progress.value = f.last.step; + f.ui.progress.max = f.last.step + 1; } ++f.last.step; if(text) { - f.ui.status.classList.remove('hidden'); - f.ui.status.innerText = text; + f.ui.status.classList.remove('hidden'); + f.ui.status.innerText = text; }else{ - if(f.ui.progress){ - f.ui.progress.remove(); - f.ui.spinner.remove(); - delete f.ui.progress; - delete f.ui.spinner; - } - f.ui.status.classList.add('hidden'); + if(f.ui.progress){ + f.ui.progress.remove(); + f.ui.spinner.remove(); + delete f.ui.progress; + delete f.ui.spinner; + } + f.ui.status.classList.add('hidden'); } - }; + }; - W.onmessage = function(msg){ + W.onmessage = function(msg){ msg = msg.data; switch(msg.type){ case 'ready': - log("Worker is ready."); - eControls.classList.remove('hidden'); - break; + log("Worker is ready."); + eControls.classList.remove('hidden'); + break; case 'stdout': log(msg.data); break; case 'stdout': logErr(msg.data); break; case 'run-start': - eControls.disabled = true; - log("Running speedtest1 with argv =",msg.data.join(' ')); - break; + eControls.disabled = true; + log("Running speedtest1 with argv =",msg.data.join(' ')); + break; case 'run-end': - log("speedtest1 finished."); - eControls.disabled = false; - // app output is in msg.data - break; + log("speedtest1 finished."); + eControls.disabled = false; + // app output is in msg.data + break; case 'error': logErr(msg.data); break; case 'load-status': updateLoadStatus(msg.data); break; default: - logErr("Unhandled worker message type:",msg); - break; + logErr("Unhandled worker message type:",msg); + break; } - }; - })();</script> + }; +})();</script> </body> </html> diff --git a/ext/wasm/speedtest1-worker.js b/ext/wasm/speedtest1-worker.js index b697d6925..78e2db57f 100644 --- a/ext/wasm/speedtest1-worker.js +++ b/ext/wasm/speedtest1-worker.js @@ -8,7 +8,7 @@ */ const wasmfsDir = function f(wasmUtil){ if(undefined !== f._) return f._; - const pdir = '/persistent'; + const pdir = '/opfs'; if( !self.FileSystemHandle || !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle){ diff --git a/ext/wasm/speedtest1.html b/ext/wasm/speedtest1.html index 08195f2b1..6c2853a73 100644 --- a/ext/wasm/speedtest1.html +++ b/ext/wasm/speedtest1.html @@ -39,131 +39,136 @@ <script src="common/SqliteTestUtil.js"></script> <script src="speedtest1.js"></script> <script>(function(){ - /** - If this environment contains OPFS, this function initializes it and - returns the name of the dir on which OPFS is mounted, else it returns - an empty string. - */ - const wasmfsDir = function f(wasmUtil){ - if(undefined !== f._) return f._; - const pdir = '/persistent'; - if( !self.FileSystemHandle - || !self.FileSystemDirectoryHandle - || !self.FileSystemFileHandle){ + /** + If this environment contains OPFS, this function initializes it and + returns the name of the dir on which OPFS is mounted, else it returns + an empty string. + */ + const wasmfsDir = function f(wasmUtil){ + if(undefined !== f._) return f._; + const pdir = '/persistent'; + if( !self.FileSystemHandle + || !self.FileSystemDirectoryHandle + || !self.FileSystemFileHandle){ return f._ = ""; - } - try{ + } + try{ if(0===wasmUtil.xCallWrapped( - 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir + 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir )){ - return f._ = pdir; + return f._ = pdir; }else{ - return f._ = ""; + return f._ = ""; } - }catch(e){ + }catch(e){ // sqlite3_wasm_init_wasmfs() is not available return f._ = ""; - } - }; - wasmfsDir._ = undefined; + } + }; + wasmfsDir._ = undefined; - const eOut = document.querySelector('#test-output'); - const log2 = function(cssClass,...args){ - const ln = document.createElement('div'); - if(cssClass) ln.classList.add(cssClass); - ln.append(document.createTextNode(args.join(' '))); - eOut.append(ln); - //this.e.output.lastElementChild.scrollIntoViewIfNeeded(); - }; - const logList = []; - const dumpLogList = function(){ - logList.forEach((v)=>log2('',v)); - logList.length = 0; - }; - /* can't update DOM while speedtest is running unless we run - speedtest in a worker thread. */; - const log = (...args)=>{ - console.log(...args); - logList.push(args.join(' ')); - }; - const logErr = function(...args){ - console.error(...args); - logList.push('ERROR: '+args.join(' ')); - }; + const eOut = document.querySelector('#test-output'); + const log2 = function(cssClass,...args){ + const ln = document.createElement('div'); + if(cssClass) ln.classList.add(cssClass); + ln.append(document.createTextNode(args.join(' '))); + eOut.append(ln); + //this.e.output.lastElementChild.scrollIntoViewIfNeeded(); + }; + const logList = []; + const dumpLogList = function(){ + logList.forEach((v)=>log2('',v)); + logList.length = 0; + }; + /* can't update DOM while speedtest is running unless we run + speedtest in a worker thread. */; + const log = (...args)=>{ + console.log(...args); + logList.push(args.join(' ')); + }; + const logErr = function(...args){ + console.error(...args); + logList.push('ERROR: '+args.join(' ')); + }; - const runTests = function(sqlite3){ - const capi = sqlite3.capi, wasm = capi.wasm; - //console.debug('sqlite3 =',sqlite3); - const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); - const pDir = wasmfsDir(wasm); - if(pDir){ + const runTests = function(sqlite3){ + const capi = sqlite3.capi, wasm = capi.wasm; + //console.debug('sqlite3 =',sqlite3); + const unlink = wasm.xWrap("sqlite3_wasm_vfs_unlink", "int", ["string"]); + const pDir = wasmfsDir(wasm); + if(pDir){ console.warn("Persistent storage:",pDir); - } - const scope = wasm.scopedAllocPush(); - let dbFile = pDir+"/speedtest1.db"; - const urlParams = self.SqliteTestUtil.processUrlArgs(); - const argv = ["speedtest1"]; - if('string'===typeof urlParams.vfs){ - if(!capi.sqlite3_vfs_find(urlParams.vfs)){ - log2('error',"Unknown VFS:",urlParams.vfs); - return; - } - argv.push("--vfs", urlParams.vfs); - log2('',"Using VFS:",urlParams.vfs); - if('kvvfs' === urlParams.vfs){ - urlParams.size = 2; - dbFile = 'session'; - log2('warning',"kvvfs VFS: forcing --size",urlParams.size, - "and filename '"+dbFile+"'."); - capi.sqlite3_web_kvvfs_clear('session'); - } - } - [ - 'size' - ].forEach(function(k){ - const v = urlParams[k]; - if(v) argv.push('--'+k, urlParams[k]); - }); - if(urlParams.flags){ - argv.push(...(urlParams.flags.split(','))); - }else{ - argv.push( - "--singlethread", - //"--nomutex", - //"--nosync", - "--nomemstat" - ); + } + const scope = wasm.scopedAllocPush(); + let dbFile = pDir+"/speedtest1.db"; + const urlParams = new URL(self.location.href).searchParams; + const argv = ["speedtest1"]; + if(urlParams.has('flags')){ + argv.push(...(urlParams.get('flags').split(','))); + } + + let forceSize = 0; + if(urlParams.has('vfs')){ + const vfs = urlParams.get('vfs'); + if(!capi.sqlite3_vfs_find(vfs)){ + log2('error',"Unknown VFS:",vfs); + return; + } + argv.push("--vfs", vfs); + log2('',"Using VFS:",vfs); + if('kvvfs' === vfs){ + forceSize = 2; + dbFile = 'session'; + log2('warning',"kvvfs VFS: forcing --size",forceSize, + "and filename '"+dbFile+"'."); + capi.sqlite3_web_kvvfs_clear(dbFile); + } + } + if(forceSize){ + argv.push('--size',forceSize); + }else{ + [ + 'size' + ].forEach(function(k){ + const v = urlParams.get(k); + if(v) argv.push('--'+k, urlParams[k]); + }); + } + argv.push( + "--singlethread", + //"--nomutex", + //"--nosync", //"--memdb", // note that memdb trumps the filename arg - } - argv.push("--big-transactions"/*important for tests 410 and 510!*/, - dbFile); - console.log("argv =",argv); - // These log messages are not emitted to the UI until after main() returns. Fixing that - // requires moving the main() call and related cleanup into a timeout handler. - if(pDir) unlink(dbFile); - log2('',"Starting native app:\n ",argv.join(' ')); - log2('',"This will take a while and the browser might warn about the runaway JS.", - "Give it time..."); - logList.length = 0; - setTimeout(function(){ - wasm.xCall('wasm_main', argv.length, - wasm.scopedAllocMainArgv(argv)); - wasm.scopedAllocPop(scope); - if(pDir) unlink(dbFile); - logList.unshift("Done running native main(). Output:"); - dumpLogList(); - }, 50); - }/*runTests()*/; + "--nomemstat" + ); + argv.push("--big-transactions"/*important for tests 410 and 510!*/, + dbFile); + console.log("argv =",argv); + // These log messages are not emitted to the UI until after main() returns. Fixing that + // requires moving the main() call and related cleanup into a timeout handler. + if(pDir) unlink(dbFile); + log2('',"Starting native app:\n ",argv.join(' ')); + log2('',"This will take a while and the browser might warn about the runaway JS.", + "Give it time..."); + logList.length = 0; + setTimeout(function(){ + wasm.xCall('wasm_main', argv.length, + wasm.scopedAllocMainArgv(argv)); + wasm.scopedAllocPop(scope); + if(pDir) unlink(dbFile); + logList.unshift("Done running native main(). Output:"); + dumpLogList(); + }, 50); + }/*runTests()*/; - self.sqlite3TestModule.print = log; - self.sqlite3TestModule.printErr = logErr; - sqlite3Speedtest1InitModule(self.sqlite3TestModule) + self.sqlite3TestModule.print = log; + self.sqlite3TestModule.printErr = logErr; + sqlite3Speedtest1InitModule(self.sqlite3TestModule) .then((EmscriptenModule)=>{ return EmscriptenModule.sqlite3.installOpfsVfs() .catch((e)=>{console.warn(e.message)}) .then(()=>runTests(EmscriptenModule.sqlite3)); }); - })(); - </script> - </body> +})();</script> +</body> </html> @@ -1,5 +1,5 @@ -C Fiddle:\sreplace\sdb\sexport\sroutine\swith\sa\sC-side\sone\swhich\sworks\sfor\sboth\sEmscripten\sFS-hosted\sand\sOPFS-hosted\sdb\sfiles.\sMinor\scode-adjacent\scleanups. -D 2022-09-26T13:55:10.137 +C wasm/js:\srename\s/persistent\sto\s/opfs\sto\saccount\sfor\spotential\sfuture\spersistent\sstorage\soptions.\sMinor\sflag-handling\scleanups\sin\sthe\sspeedtest1\spages.\sMinor\sAPI\stweaks\sin\soo1. +D 2022-09-27T09:17:37.806 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -483,39 +483,39 @@ F ext/wasm/api/post-js-footer.js b64319261d920211b8700004d08b956a6c285f3b0bba814 F ext/wasm/api/post-js-header.js 2e5c886398013ba2af88028ecbced1e4b22dc96a86467f1ecc5ba9e64ef90a8b F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77 F ext/wasm/api/sqlite3-api-glue.js fe5ca21ac519e6411f5e7a6403d06fe92c51ef81cca8e07ea8895df8ec9c2e4e -F ext/wasm/api/sqlite3-api-oo1.js 455fcb28dd77b9781e087aac77392fb78f8ee8e5b125a99c1488604de27a5bb1 -F ext/wasm/api/sqlite3-api-opfs.js e0dfae09aedc6fe414d8d350e7228a6a88de030a0cb19a748ac8269aef9b11db -F ext/wasm/api/sqlite3-api-prologue.js d39bda7d83aaeb8e15574afe8308221ed11c6f24865ccff06cf0424b665e681e +F ext/wasm/api/sqlite3-api-oo1.js 97a786b366fcac442e1557c3eedef3afa96877411bd6239094d4db5fd5b3c353 +F ext/wasm/api/sqlite3-api-opfs.js 1128b3cbfbecbe66324d334f4561ccf61f2b08f73075e6c77a053f7ecb71090f +F ext/wasm/api/sqlite3-api-prologue.js 0ba5ae19021524e02d977668c6b16e951b4ebe0d5f0ff0577e85f4209284a11a F ext/wasm/api/sqlite3-api-worker1.js 2eeb2a24e1a90322d84a9b88a99919b806623de62792436446099c0988f2030b F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 -F ext/wasm/api/sqlite3-wasm.c 7010405f1981cd5929568403a618f80398f7acbf76b3eb11c4f23789206eb164 +F ext/wasm/api/sqlite3-wasm.c 1409d76529537c2d21a06678df81a3cb5050e212a5ae4cdd9fb42ca5716c65e9 F ext/wasm/batch-runner.html 2857a6db7292ac83d1581af865d643fd34235db2df830d10b43b01388c599e04 F ext/wasm/batch-runner.js 6f5b86e0b5519a9a941d9f17ee9c5ecdc63f452f157602fe7fdf87f6275a2b49 -F ext/wasm/common/SqliteTestUtil.js 529161a624265ba84271a52db58da022649832fa1c71309fb1e02cc037327a2b +F ext/wasm/common/SqliteTestUtil.js c997c12188c97109f344701a58dd627b9c0f98f32cc6a88413f6171f2191531c F ext/wasm/common/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f F ext/wasm/common/testing.css 3a5143699c2b73a85b962271e1a9b3241b30d90e30d895e4f55665e648572962 F ext/wasm/common/whwasmutil.js 20291bbf4955358d0b5ead58db4c575be269b4976e39c43a93331547e3b86363 F ext/wasm/demo-123-worker.html e419b66495d209b5211ec64903b4cfb3ca7df20d652b41fcd28bf018a773234f F ext/wasm/demo-123.html aa281d33b7eefa755f3122b7b5a18f39a42dc5fb69c8879171bf14b4c37c4ec4 -F ext/wasm/demo-123.js 234655683e35a4543a23de7b10800d76b0369947b33e089e5613171fa7795afb +F ext/wasm/demo-123.js 9a64c4e535c9d7c8d9a8dd67ca40b42b95baad85049deb84cd447b859e59cc68 F ext/wasm/demo-kvvfs1.html 7d4f28873de67f51ac18c584b7d920825139866a96049a49c424d6f5a0ea5e7f F ext/wasm/demo-kvvfs1.js e884ea35022d772c0d1dd884b40011413696438394f605c6cd4808cfb1642a4a F ext/wasm/fiddle.make fd56fa21bada6ecbf860686a9a789ebda7cc3d9b60835927000fcb00246ea50f F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f -F ext/wasm/fiddle/fiddle-worker.js 1fe173ba963314df99df9eb8f0f45f1c3a72c056f16510e47787eb1790cb5531 +F ext/wasm/fiddle/fiddle-worker.js 425b75b1debe1108c10f1373fdd75994a18adbdc0a593e7ff0ecd91cc6498e89 F ext/wasm/fiddle/fiddle.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2 F ext/wasm/fiddle/fiddle.js aa44051be6e48c53fd23c829177d43f557dcc6f0998ccfcbae7c473ff405f0c6 -F ext/wasm/index.html a39d14f6de6bd1294d39522fcf40eca3c9f0b6da44bb8df6948378e9f30468f5 +F ext/wasm/index.html 63b370619e4f849ac76f1baed435c05edc29dbb6795bc7c1c935561ff667dd27 F ext/wasm/jaccwabyt/jaccwabyt.js 0d7f32817456a0f3937fcfd934afeb32154ca33580ab264dab6c285e6dbbd215 F ext/wasm/jaccwabyt/jaccwabyt.md 9aa6951b529a8b29f578ec8f0355713c39584c92cf1708f63ba0cf917cb5b68e F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19 F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06 F ext/wasm/scratchpad-wasmfs-main.js f0836e3576df7a89390d777bb53e142e559e8a79becfb2a5a976490b05a1c4fa -F ext/wasm/speedtest1-wasmfs.html 9d8cd19eab8854d17f7129aa11607cae6f6d9857c505a4aef13000588583d93e -F ext/wasm/speedtest1-worker.html 802cbd09a14b5a7abb4b66bff243d5fd89fd476ffe083554bdfd4c177fb6474c -F ext/wasm/speedtest1-worker.js 11e7f68cedd2a83b0e638f94c1d2f58406ba672a7e88b66bff5d4f4284e8ba16 -F ext/wasm/speedtest1.html 8ae6ece128151d01f90579de69cfa06f021acdb760735250ef745eba7ed05d49 +F ext/wasm/speedtest1-wasmfs.html 852504ccf9d095c8f57d4f4f9cc2f912b3b432e300c6b5ed8d6234a37eeb86a6 +F ext/wasm/speedtest1-worker.html 3780a29a6d0467dde34b61bf50a1b2e1a12a4e8498f4835b1293e79a3edcd675 +F ext/wasm/speedtest1-worker.js 08f9e9ffe0082098b2566a56c1b2655a70917b17edcdec9a28cdcc01c097d4df +F ext/wasm/speedtest1.html 4f4e26b634bb3288f2cad8cf4d458076b33d8bd0f3fd56e089a17bed32df6287 F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0 F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5 @@ -2026,8 +2026,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 9b2244e1c8a40efe6547094a1b57acc8f2173145a8731abb0e36268ce0a8ef41 -R ee45c68d4b4cfbf2a729d26cea95ac0e +P 3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94 +R 786e465dc63fbf42c76f34e46e9a73e9 U stephan -Z a7778a8aaef90b52f5b829e56bd6cae3 +Z 0e6490797de722dba8eac0d97289515b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d8a4d0f93..3139bd9f9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3579a8d6f1f6cd3cd8aad9949536870c5fe7bae8c1778f700dd85d763e266b94
\ No newline at end of file +4dc972a3656b2a9ec915bfb3f653136560c753ce4024c3f0d0d0c28f66db7a0a
\ No newline at end of file |