1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

OPFS VFS: further internal refactoring towards experimenting with a new comms model.

FossilOrigin-Name: 5ca412ced24b4e3af5f467e710a597ed440badf7b8335346aade11d3cad3d1a1
This commit is contained in:
stephan
2022-09-20 03:31:02 +00:00
parent c4b87be3e8
commit 138647a552
4 changed files with 184 additions and 72 deletions

View File

@ -128,7 +128,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
// failure is, e.g., that the remote script is 404. // failure is, e.g., that the remote script is 404.
promiseReject(new Error("Loading OPFS async Worker failed for unknown reasons.")); promiseReject(new Error("Loading OPFS async Worker failed for unknown reasons."));
}; };
const wMsg = (type,payload)=>W.postMessage({type,payload}); const wMsg = (type,args)=>W.postMessage({type,args});
/** /**
Generic utilities for working with OPFS. This will get filled out Generic utilities for working with OPFS. This will get filled out
by the Promise setup and, on success, installed as sqlite3.opfs. by the Promise setup and, on success, installed as sqlite3.opfs.
@ -186,36 +186,48 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
require a bit of acrobatics but should be feasible. require a bit of acrobatics but should be feasible.
*/ */
const state = Object.create(null); const state = Object.create(null);
state.littleEndian = true;
state.verbose = options.verbose; state.verbose = options.verbose;
state.fileBufferSize = state.fileBufferSize =
1024 * 64 /* size of aFileHandle.sab. 64k = max sqlite3 page 1024 * 64 /* size of aFileHandle.sab. 64k = max sqlite3 page
size. */; size. */;
state.sabOffsetS11n = state.fileBufferSize; state.sabS11nOffset = state.fileBufferSize;
state.sabS11nSize = 2048;
state.sabIO = new SharedArrayBuffer( state.sabIO = new SharedArrayBuffer(
state.fileBufferSize state.fileBufferSize
+ 4096/* arg/result serialization */ + state.sabS11nSize/* arg/result serialization block */
+ 8 /* to be removed - porting crutch */
); );
state.fbInt64Offset =
state.sabIO.byteLength - 8 /*spot in fileHandle.sab to store an int64 result.
to be removed. Porting crutch. */;
state.opIds = Object.create(null); state.opIds = Object.create(null);
state.rcIds = Object.create(null);
const metrics = Object.create(null); const metrics = Object.create(null);
{ {
let i = 0; let i = 0;
state.opIds.whichOp = i++;
state.opIds.nothing = i++; state.opIds.nothing = i++;
state.opIds.xAccess = i++; state.opIds.xAccess = i++;
state.rcIds.xAccess = i++;
state.opIds.xClose = i++; state.opIds.xClose = i++;
state.rcIds.xClose = i++;
state.opIds.xDelete = i++; state.opIds.xDelete = i++;
state.rcIds.xDelete = i++;
state.opIds.xDeleteNoWait = i++; state.opIds.xDeleteNoWait = i++;
state.rcIds.xDeleteNoWait = i++;
state.opIds.xFileSize = i++; state.opIds.xFileSize = i++;
state.rcIds.xFileSize = i++;
state.opIds.xOpen = i++; state.opIds.xOpen = i++;
state.rcIds.xOpen = i++;
state.opIds.xRead = i++; state.opIds.xRead = i++;
state.rcIds.xRead = i++;
state.opIds.xSleep = i++; state.opIds.xSleep = i++;
state.rcIds.xSleep = i++;
state.opIds.xSync = i++; state.opIds.xSync = i++;
state.rcIds.xSync = i++;
state.opIds.xTruncate = i++; state.opIds.xTruncate = i++;
state.rcIds.xTruncate = i++;
state.opIds.xWrite = i++; state.opIds.xWrite = i++;
state.rcIds.xWrite = i++;
state.opIds.mkdir = i++; state.opIds.mkdir = i++;
state.rcIds.mkdir = i++;
state.sabOP = new SharedArrayBuffer(i * 4/*sizeof int32*/); state.sabOP = new SharedArrayBuffer(i * 4/*sizeof int32*/);
state.opIds.xFileControl = state.opIds.xSync /* special case */; state.opIds.xFileControl = state.opIds.xSync /* special case */;
opfsUtil.metrics.reset(); opfsUtil.metrics.reset();
@ -247,7 +259,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
must be a single object or primitive value, depending on the must be a single object or primitive value, depending on the
given operation's signature in the async API counterpart. given operation's signature in the async API counterpart.
*/ */
const opRun = (op,args)=>{ const opRun = (op,...args)=>{
const t = performance.now(); const t = performance.now();
Atomics.store(state.sabOPView, state.opIds[op], -1); Atomics.store(state.sabOPView, state.opIds[op], -1);
wMsg(op, args); wMsg(op, args);
@ -256,6 +268,44 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
return Atomics.load(state.sabOPView, state.opIds[op]); return Atomics.load(state.sabOPView, state.opIds[op]);
}; };
const initS11n = ()=>{
// Achtung: this code is 100% duplicated in the other half of this proxy!
if(state.s11n) return state.s11n;
const jsonDecoder = new TextDecoder(),
jsonEncoder = new TextEncoder('utf-8'),
viewSz = new DataView(state.sabIO, state.sabS11nOffset, 4),
viewJson = new Uint8Array(state.sabIO, state.sabS11nOffset+4, state.sabS11nSize-4);
state.s11n = Object.create(null);
/**
Returns an array of the state serialized by the most recent
serialize() operation (here or in the counterpart thread), or
null if the serialization buffer is empty.
*/
state.s11n.deserialize = function(){
const sz = viewSz.getInt32(0, state.littleEndian);
const json = sz ? jsonDecoder.decode(
viewJson.slice(0, sz)
/* slice() (copy) needed, instead of subarray() (reference),
because TextDecoder throws if asked to decode from an
SAB. */
) : null;
return JSON.parse(json);
}
/**
Serializes all arguments to the shared buffer for consumption
by the counterpart thread. This impl currently uses JSON for
serialization for simplicy of implementation, but if that
proves imperformant then a lower-level approach will be
created.
*/
state.s11n.serialize = function(...args){
const json = jsonEncoder.encode(JSON.stringify(args));
viewSz.setInt32(0, json.byteLength, state.littleEndian);
viewJson.set(json);
};
return state.s11n;
};
/** /**
Generates a random ASCII string len characters long, intended for Generates a random ASCII string len characters long, intended for
use as a temporary file name. use as a temporary file name.
@ -425,7 +475,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
xFileControl: function(pFile, opId, pArg){ xFileControl: function(pFile, opId, pArg){
mTimeStart('xFileControl'); mTimeStart('xFileControl');
const rc = (capi.SQLITE_FCNTL_SYNC===opId) const rc = (capi.SQLITE_FCNTL_SYNC===opId)
? opRun('xSync', {fid:pFile, flags:0}) ? opRun('xSync', pFile, 0)
: capi.SQLITE_NOTFOUND; : capi.SQLITE_NOTFOUND;
mTimeEnd(); mTimeEnd();
return rc; return rc;
@ -434,10 +484,8 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
mTimeStart('xFileSize'); mTimeStart('xFileSize');
const rc = opRun('xFileSize', pFile); const rc = opRun('xFileSize', pFile);
if(!isWorkerErrCode(rc)){ if(!isWorkerErrCode(rc)){
wasm.setMemValue( const sz = state.s11n.deserialize()[0];
pSz64, __openFiles[pFile].sabViewFileSize.getBigInt64(0,true), wasm.setMemValue(pSz64, BigInt(sz), 'i64');
'i64'
);
} }
mTimeEnd(); mTimeEnd();
return rc; return rc;
@ -447,14 +495,13 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
//warn("xLock(",arguments,") is a no-op"); //warn("xLock(",arguments,") is a no-op");
return 0; return 0;
}, },
xRead: function(pFile,pDest,n,offset){ xRead: function(pFile,pDest,n,offset64){
/* int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst) */ /* int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst) */
mTimeStart('xRead'); mTimeStart('xRead');
const f = __openFiles[pFile]; const f = __openFiles[pFile];
let rc; let rc;
try { try {
// FIXME(?): block until we finish copying the xRead result buffer. How? rc = opRun('xRead',pFile, n, Number(offset64));
rc = opRun('xRead',{fid:pFile, n, offset});
if(0===rc || capi.SQLITE_IOERR_SHORT_READ===rc){ if(0===rc || capi.SQLITE_IOERR_SHORT_READ===rc){
// set() seems to be the fastest way to copy this... // set() seems to be the fastest way to copy this...
wasm.heap8u().set(f.sabView.subarray(0, n), pDest); wasm.heap8u().set(f.sabView.subarray(0, n), pDest);
@ -468,11 +515,11 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
}, },
xSync: function(pFile,flags){ xSync: function(pFile,flags){
++metrics.xSync.count; ++metrics.xSync.count;
return 0; // impl'd in xFileControl(). opRun('xSync', {fid:pFile, flags}); return 0; // impl'd in xFileControl()
}, },
xTruncate: function(pFile,sz64){ xTruncate: function(pFile,sz64){
mTimeStart('xTruncate'); mTimeStart('xTruncate');
const rc = opRun('xTruncate', {fid:pFile, size: sz64}); const rc = opRun('xTruncate', pFile, Number(sz64));
mTimeEnd(); mTimeEnd();
return rc; return rc;
}, },
@ -481,15 +528,14 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
//warn("xUnlock(",arguments,") is a no-op"); //warn("xUnlock(",arguments,") is a no-op");
return 0; return 0;
}, },
xWrite: function(pFile,pSrc,n,offset){ xWrite: function(pFile,pSrc,n,offset64){
/* int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst) */ /* int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst) */
mTimeStart('xWrite'); mTimeStart('xWrite');
const f = __openFiles[pFile]; const f = __openFiles[pFile];
let rc; let rc;
try { try {
// FIXME(?): block from here until we finish the xWrite. How?
f.sabView.set(wasm.heap8u().subarray(pSrc, pSrc+n)); f.sabView.set(wasm.heap8u().subarray(pSrc, pSrc+n));
rc = opRun('xWrite',{fid:pFile, n, offset}); rc = opRun('xWrite', pFile, n, Number(offset64));
}catch(e){ }catch(e){
error("xWrite(",arguments,") failed:",e,f); error("xWrite(",arguments,") failed:",e,f);
rc = capi.SQLITE_IOERR_WRITE; rc = capi.SQLITE_IOERR_WRITE;
@ -527,7 +573,7 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
}, },
xDelete: function(pVfs, zName, doSyncDir){ xDelete: function(pVfs, zName, doSyncDir){
mTimeStart('xDelete'); mTimeStart('xDelete');
opRun('xDelete', {filename: wasm.cstringToJs(zName), syncDir: doSyncDir}); opRun('xDelete', wasm.cstringToJs(zName), doSyncDir, false);
/* We're ignoring errors because we cannot yet differentiate /* We're ignoring errors because we cannot yet differentiate
between harmless and non-harmless failures. */ between harmless and non-harmless failures. */
mTimeEnd(); mTimeEnd();
@ -577,24 +623,22 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
}else if('number'===typeof zName){ }else if('number'===typeof zName){
zName = wasm.cstringToJs(zName); zName = wasm.cstringToJs(zName);
} }
const args = Object.create(null); const fh = Object.create(null);
args.fid = pFile; fh.fid = pFile;
args.filename = zName; fh.filename = zName;
args.sab = new SharedArrayBuffer(state.fileBufferSize); fh.sab = new SharedArrayBuffer(state.fileBufferSize);
args.flags = flags; fh.flags = flags;
const rc = opRun('xOpen', args); const rc = opRun('xOpen', pFile, zName, flags);
if(!rc){ if(!rc){
/* Recall that sqlite3_vfs::xClose() will be called, even on /* Recall that sqlite3_vfs::xClose() will be called, even on
error, unless pFile->pMethods is NULL. */ error, unless pFile->pMethods is NULL. */
if(args.readOnly){ if(fh.readOnly){
wasm.setMemValue(pOutFlags, capi.SQLITE_OPEN_READONLY, 'i32'); wasm.setMemValue(pOutFlags, capi.SQLITE_OPEN_READONLY, 'i32');
} }
__openFiles[pFile] = args; __openFiles[pFile] = fh;
args.sabView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); fh.sabView = state.sabFileBufView;
args.sabViewFileSize = new DataView(state.sabIO, state.fbInt64Offset, 8); fh.sq3File = new sqlite3_file(pFile);
args.sq3File = new sqlite3_file(pFile); fh.sq3File.$pMethods = opfsIoMethods.pointer;
args.sq3File.$pMethods = opfsIoMethods.pointer;
args.ba = new Uint8Array(args.sab);
} }
mTimeEnd(); mTimeEnd();
return rc; return rc;
@ -640,13 +684,17 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
but cannot report the nature of the failure. but cannot report the nature of the failure.
*/ */
opfsUtil.deleteEntry = function(fsEntryName,recursive=false){ opfsUtil.deleteEntry = function(fsEntryName,recursive=false){
return 0===opRun('xDelete', {filename:fsEntryName, recursive}); return 0===opRun('xDelete', fsEntryName, 0, recursive);
}; };
/** /**
Exactly like deleteEntry() but runs asynchronously. Exactly like deleteEntry() but runs asynchronously. This is a
"fire and forget" operation: it does not return a promise
because the counterpart operation happens in another thread and
waiting on that result in a Promise would block the OPFS VFS
from acting until it completed.
*/ */
opfsUtil.deleteEntryAsync = async function(fsEntryName,recursive=false){ opfsUtil.deleteEntryAsync = function(fsEntryName,recursive=false){
wMsg('xDeleteNoWait', {filename: fsEntryName, recursive}); wMsg('xDeleteNoWait', [fsEntryName, 0, recursive]);
}; };
/** /**
Synchronously creates the given directory name, recursively, in Synchronously creates the given directory name, recursively, in
@ -753,11 +801,11 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
W.onmessage = function({data}){ W.onmessage = function({data}){
//log("Worker.onmessage:",data); //log("Worker.onmessage:",data);
switch(data.type){ switch(data.type){
case 'loaded': case 'opfs-async-loaded':
/*Pass our config and shared state on to the async worker.*/ /*Pass our config and shared state on to the async worker.*/
wMsg('init',state); wMsg('opfs-async-init',state);
break; break;
case 'inited':{ case 'opfs-async-inited':{
/*Indicates that the async partner has received the 'init', /*Indicates that the async partner has received the 'init',
so we now know that the state object is no longer subject to so we now know that the state object is no longer subject to
being copied by a pending postMessage() call.*/ being copied by a pending postMessage() call.*/
@ -772,7 +820,9 @@ sqlite3.installOpfsVfs = function callee(asyncProxyUri = callee.defaultProxyUri)
} }
capi.sqlite3_vfs_register.addReference(opfsVfs, opfsIoMethods); capi.sqlite3_vfs_register.addReference(opfsVfs, opfsIoMethods);
state.sabOPView = new Int32Array(state.sabOP); state.sabOPView = new Int32Array(state.sabOP);
state.sabFileBufView = new Uint8Array(state.sabFileBufView, 0, state.fileBufferSize); state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
initS11n();
if(options.sanityChecks){ if(options.sanityChecks){
warn("Running sanity checks because of opfs-sanity-check URL arg..."); warn("Running sanity checks because of opfs-sanity-check URL arg...");
sanityCheck(); sanityCheck();

View File

@ -220,7 +220,7 @@ const vfsAsyncImpls = {
storeAndNotify('xDelete', rc); storeAndNotify('xDelete', rc);
mTimeEnd(); mTimeEnd();
}, },
xDeleteNoWait: async function({filename, syncDir, recursive = false}){ xDeleteNoWait: async function(filename, syncDir = 0, recursive = false){
/* The syncDir flag is, for purposes of the VFS API's semantics, /* The syncDir flag is, for purposes of the VFS API's semantics,
ignored here. However, if it has the value 0x1234 then: after ignored here. However, if it has the value 0x1234 then: after
deleting the given file, recursively try to delete any empty deleting the given file, recursively try to delete any empty
@ -261,10 +261,7 @@ const vfsAsyncImpls = {
let sz; let sz;
try{ try{
sz = await fh.accessHandle.getSize(); sz = await fh.accessHandle.getSize();
if(!fh.sabViewFileSize){ state.s11n.serialize(Number(sz));
fh.sabViewFileSize = new DataView(state.sabIO,state.fbInt64Offset,8);
}
fh.sabViewFileSize.setBigInt64(0, BigInt(sz), true);
sz = 0; sz = 0;
}catch(e){ }catch(e){
error("xFileSize():",e, fh); error("xFileSize():",e, fh);
@ -273,11 +270,7 @@ const vfsAsyncImpls = {
storeAndNotify('xFileSize', sz); storeAndNotify('xFileSize', sz);
mTimeEnd(); mTimeEnd();
}, },
xOpen: async function({ xOpen: async function(fid/*sqlite3_file pointer*/, filename, flags){
fid/*sqlite3_file pointer*/,
filename,
flags
}){
const opName = 'xOpen'; const opName = 'xOpen';
mTimeStart(opName); mTimeStart(opName);
log(opName+"(",arguments[0],")"); log(opName+"(",arguments[0],")");
@ -316,7 +309,7 @@ const vfsAsyncImpls = {
} }
mTimeEnd(); mTimeEnd();
}, },
xRead: async function({fid,n,offset}){ xRead: async function(fid,n,offset){
mTimeStart('xRead'); mTimeStart('xRead');
log("xRead(",arguments[0],")"); log("xRead(",arguments[0],")");
let rc = 0; let rc = 0;
@ -337,7 +330,7 @@ const vfsAsyncImpls = {
storeAndNotify('xRead',rc); storeAndNotify('xRead',rc);
mTimeEnd(); mTimeEnd();
}, },
xSync: async function({fid,flags/*ignored*/}){ xSync: async function(fid,flags/*ignored*/){
mTimeStart('xSync'); mTimeStart('xSync');
log("xSync(",arguments[0],")"); log("xSync(",arguments[0],")");
const fh = __openFiles[fid]; const fh = __openFiles[fid];
@ -345,14 +338,14 @@ const vfsAsyncImpls = {
storeAndNotify('xSync',0); storeAndNotify('xSync',0);
mTimeEnd(); mTimeEnd();
}, },
xTruncate: async function({fid,size}){ xTruncate: async function(fid,size){
mTimeStart('xTruncate'); mTimeStart('xTruncate');
log("xTruncate(",arguments[0],")"); log("xTruncate(",arguments[0],")");
let rc = 0; let rc = 0;
const fh = __openFiles[fid]; const fh = __openFiles[fid];
try{ try{
affirmNotRO('xTruncate', fh); affirmNotRO('xTruncate', fh);
await fh.accessHandle.truncate(Number(size)); await fh.accessHandle.truncate(size);
}catch(e){ }catch(e){
error("xTruncate():",e,fh); error("xTruncate():",e,fh);
rc = state.sq3Codes.SQLITE_IOERR_TRUNCATE; rc = state.sq3Codes.SQLITE_IOERR_TRUNCATE;
@ -360,7 +353,7 @@ const vfsAsyncImpls = {
storeAndNotify('xTruncate',rc); storeAndNotify('xTruncate',rc);
mTimeEnd(); mTimeEnd();
}, },
xWrite: async function({fid,n,offset}){ xWrite: async function(fid,n,offset){
mTimeStart('xWrite'); mTimeStart('xWrite');
log("xWrite(",arguments[0],")"); log("xWrite(",arguments[0],")");
let rc; let rc;
@ -380,6 +373,70 @@ const vfsAsyncImpls = {
} }
}; };
const initS11n = ()=>{
// Achtung: this code is 100% duplicated in the other half of this proxy!
if(state.s11n) return state.s11n;
const jsonDecoder = new TextDecoder(),
jsonEncoder = new TextEncoder('utf-8'),
viewSz = new DataView(state.sabIO, state.sabS11nOffset, 4),
viewJson = new Uint8Array(state.sabIO, state.sabS11nOffset+4, state.sabS11nSize-4);
state.s11n = Object.create(null);
/**
Returns an array of the state serialized by the most recent
serialize() operation (here or in the counterpart thread), or
null if the serialization buffer is empty.
*/
state.s11n.deserialize = function(){
const sz = viewSz.getInt32(0, state.littleEndian);
const json = sz ? jsonDecoder.decode(
viewJson.slice(0, sz)
/* slice() (copy) needed, instead of subarray() (reference),
because TextDecoder throws if asked to decode from an
SAB. */
) : null;
return JSON.parse(json);
}
/**
Serializes all arguments to the shared buffer for consumption
by the counterpart thread. This impl currently uses JSON for
serialization for simplicy of implementation, but if that
proves imperformant then a lower-level approach will be
created.
*/
state.s11n.serialize = function(...args){
const json = jsonEncoder.encode(JSON.stringify(args));
viewSz.setInt32(0, json.byteLength, state.littleEndian);
viewJson.set(json);
};
return state.s11n;
};
const waitLoop = function(){
const opHandlers = Object.create(null);
for(let k of Object.keys(state.opIds)){
const o = Object.create(null);
opHandlers[state.opIds[k]] = o;
o.key = k;
}
const sabOP = state.sabOP;
for(;;){
try {
Atomics.store(sabOP, state.opIds.whichOp, 0);
Atomic.wait(sabOP, state.opIds.whichOp);
const opId = Atomics.load(sabOP, state.opIds.whichOp);
const hnd = opHandlers[opId] ?? toss("No waitLoop handler for whichOp #",opId);
const args = state.s11n.deserialize();
log("whichOp =",opId,hnd,args);
const rc = 0/*TODO: run op*/;
Atomics.store(sabOP, state.rcIds[hnd.key], rc);
Atomics.notify(sabOP, state.rcIds[hnd.key]);
}catch(e){
error('in waitLoop():',e.message);
}
}
};
navigator.storage.getDirectory().then(function(d){ navigator.storage.getDirectory().then(function(d){
const wMsg = (type)=>postMessage({type}); const wMsg = (type)=>postMessage({type});
state.rootDir = d; state.rootDir = d;
@ -387,33 +444,38 @@ navigator.storage.getDirectory().then(function(d){
self.onmessage = async function({data}){ self.onmessage = async function({data}){
log("self.onmessage()",data); log("self.onmessage()",data);
switch(data.type){ switch(data.type){
case 'init':{ case 'opfs-async-init':{
/* Receive shared state from synchronous partner */ /* Receive shared state from synchronous partner */
const opt = data.payload; const opt = data.args;
state.littleEndian = opt.littleEndian;
state.verbose = opt.verbose ?? 2; state.verbose = opt.verbose ?? 2;
state.fileBufferSize = opt.fileBufferSize; state.fileBufferSize = opt.fileBufferSize;
state.fbInt64Offset = opt.fbInt64Offset; state.sabS11nOffset = opt.sabS11nOffset;
state.sabS11nSize = opt.sabS11nSize;
state.sabOP = opt.sabOP; state.sabOP = opt.sabOP;
state.sabOPView = new Int32Array(state.sabOP); state.sabOPView = new Int32Array(state.sabOP);
state.sabIO = opt.sabIO; state.sabIO = opt.sabIO;
state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize);
state.sabS11nView = new Uint8Array(state.sabIO, state.sabS11nOffset, state.sabS11nSize);
state.opIds = opt.opIds; state.opIds = opt.opIds;
state.rcIds = opt.rcIds;
state.sq3Codes = opt.sq3Codes; state.sq3Codes = opt.sq3Codes;
Object.keys(vfsAsyncImpls).forEach((k)=>{ Object.keys(vfsAsyncImpls).forEach((k)=>{
if(!Number.isFinite(state.opIds[k])){ if(!Number.isFinite(state.opIds[k])){
toss("Maintenance required: missing state.opIds[",k,"]"); toss("Maintenance required: missing state.opIds[",k,"]");
} }
}); });
initS11n();
metrics.reset(); metrics.reset();
log("init state",state); log("init state",state);
wMsg('inited'); wMsg('opfs-async-inited');
break; break;
} }
default:{ default:{
let err; let err;
const m = vfsAsyncImpls[data.type] || toss("Unknown message type:",data.type); const m = vfsAsyncImpls[data.type] || toss("Unknown message type:",data.type);
try { try {
await m(data.payload).catch((e)=>err=e); await m(...data.args).catch((e)=>err=e);
}catch(e){ }catch(e){
err = e; err = e;
} }
@ -425,5 +487,5 @@ navigator.storage.getDirectory().then(function(d){
} }
} }
}; };
wMsg('loaded'); wMsg('opfs-async-loaded');
}).catch((e)=>error(e)); }).catch((e)=>error(e));

View File

@ -1,5 +1,5 @@
C OPFS\sVFS:\smoved\si/o\sbuffer\sfrom\sper-file\sto\sthe\sVFS,\sand\srelated\srefactoring,\sin\sprep\sfor\sexperimentation\swith\sa\snew\sinter-worker\scomms\smodel. C OPFS\sVFS:\sfurther\sinternal\srefactoring\stowards\sexperimenting\swith\sa\snew\scomms\smodel.
D 2022-09-20T01:28:47.162 D 2022-09-20T03:31:02.139
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -484,7 +484,7 @@ F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a
F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77 F ext/wasm/api/sqlite3-api-cleanup.js 8564a6077cdcaea9a9f428a019af8a05887f0131e6a2a1e72a7ff1145fadfe77
F ext/wasm/api/sqlite3-api-glue.js 366d580c8e5bf7fcf4c6dee6f646c31f5549bd417ea03a59a0acca00e8ecce30 F ext/wasm/api/sqlite3-api-glue.js 366d580c8e5bf7fcf4c6dee6f646c31f5549bd417ea03a59a0acca00e8ecce30
F ext/wasm/api/sqlite3-api-oo1.js 2d13dddf0d2b4168a9249f124134d37924331e5b55e05dba18b6d661fbeefe48 F ext/wasm/api/sqlite3-api-oo1.js 2d13dddf0d2b4168a9249f124134d37924331e5b55e05dba18b6d661fbeefe48
F ext/wasm/api/sqlite3-api-opfs.js f8027fb4af1c24fcfad31889f8a5ccfa3b96d6e812d3495b13833bef57034046 F ext/wasm/api/sqlite3-api-opfs.js 351459d571166ff4cebaccd6b8aad2b0fe5eac54a8c777ba52c31c931a3eb2e2
F ext/wasm/api/sqlite3-api-prologue.js 0d2639387b94c30f492d4aea6e44fb7b16720808678464559458fd2ae3759655 F ext/wasm/api/sqlite3-api-prologue.js 0d2639387b94c30f492d4aea6e44fb7b16720808678464559458fd2ae3759655
F ext/wasm/api/sqlite3-api-worker1.js ee4cf149cbacb63d06b536674f822aa5088b7e022cdffc69f1f36cebe2f9fea0 F ext/wasm/api/sqlite3-api-worker1.js ee4cf149cbacb63d06b536674f822aa5088b7e022cdffc69f1f36cebe2f9fea0
F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9 F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
@ -519,7 +519,7 @@ F ext/wasm/speedtest1.html 512addeb3c27c94901178b7bcbde83a6f95c093f9ebe16a2959a0
F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0 F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5 F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
F ext/wasm/sqlite3-opfs-async-proxy.js 7ebc36915cd61bd4f067a4823307f4d4eb2678a173aaae470c534e8fe9cda650 F ext/wasm/sqlite3-opfs-async-proxy.js 462081970a6a46d9b2c386474aacad2d81e6629bb554d6cad5c58515f08c8a38
F ext/wasm/sqlite3-worker1-promiser.js 4fd0465688a28a75f1d4ee4406540ba494f49844e3cad0670d0437a001943365 F ext/wasm/sqlite3-worker1-promiser.js 4fd0465688a28a75f1d4ee4406540ba494f49844e3cad0670d0437a001943365
F ext/wasm/sqlite3-worker1.js 0c1e7626304543969c3846573e080c082bf43bcaa47e87d416458af84f340a9e F ext/wasm/sqlite3-worker1.js 0c1e7626304543969c3846573e080c082bf43bcaa47e87d416458af84f340a9e
F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5 F ext/wasm/test-opfs-vfs.html eb69dda21eb414b8f5e3f7c1cc0f774103cc9c0f87b2d28a33419e778abfbab5
@ -2026,8 +2026,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d1f1fe6f1c60640f7770dfb9245c459a09b8d24ec2ddf664dff77c810bd51f96 P d4d63e4580ad8d497310608175308c03c517e051d7865cb66aa0b10356612d7d
R e5a1ff53ebe902985ab8e87bba2c71fb R 7fef73d3d6085edd0d87db08b80a36c1
U stephan U stephan
Z d05962442428c5dae722ab00dca47e48 Z d9dc6ab88cc2471cfc1f140af8fec063
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
d4d63e4580ad8d497310608175308c03c517e051d7865cb66aa0b10356612d7d 5ca412ced24b4e3af5f467e710a597ed440badf7b8335346aade11d3cad3d1a1