1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

OPFS VFS now lazily opens its sync access handle, as a step towards experimenting with relinquishing it during idle times to help avoid cross-tab and page-reload locking issues.

FossilOrigin-Name: a984e1ba435731413a541f86c50232bc7d6e33aff6ba4cca90f89188e7b82a2c
This commit is contained in:
stephan
2022-10-03 09:21:37 +00:00
parent bdfd7ea03a
commit 7ff8da876d
5 changed files with 72 additions and 60 deletions

View File

@ -25,6 +25,13 @@
access to the sqlite3 JS/WASM bits, so any bits which it needs (most
notably SQLITE_xxx integer codes) have to be imported into it via an
initialization process.
Potential TODOs:
- When idle for "a long time", close the sync access handle in order
to release the lock, then re-open it on demand. Similarly, delay
fetching of the sync access handle until we need it. The intent
would be to help multi-tab access to a db avoid locking issues.
*/
'use strict';
const toss = function(...args){throw new Error(args.join(' '))};
@ -132,6 +139,17 @@ const getDirForFilename = async function f(absFilename, createDirs = false){
return [dh, filename];
};
/**
Returns the sync access handle associated with the given file
handle object (which must be a valid handle object), lazily opening
it if needed.
*/
const getSyncHandle = async (f)=>(
f.accessHandle || (
f.accessHandle =
await f.fileHandle.createSyncAccessHandle()
)
);
/**
Stores the given value at state.sabOPView[state.opIds.rc] and then
@ -294,7 +312,7 @@ const vfsAsyncImpls = {
let sz;
wTimeStart('xFileSize');
try{
sz = await fh.accessHandle.getSize();
sz = await (await getSyncHandle(fh)).getSize();
state.s11n.serialize(Number(sz));
sz = 0;
}catch(e){
@ -322,23 +340,24 @@ const vfsAsyncImpls = {
return;
}
const hFile = await hDir.getFileHandle(filenamePart, {create});
const fobj = Object.create(null);
/**
wa-sqlite, at this point, grabs a SyncAccessHandle and
assigns it to the accessHandle prop of the file state
object, but only for certain cases and it's unclear why it
places that limitation on it.
*/
fobj.accessHandle = await hFile.createSyncAccessHandle();
wTimeEnd();
const fobj = Object.assign(Object.create(null),{
filenameAbs: filename,
filenamePart: filenamePart,
dirHandle: hDir,
fileHandle: hFile,
sabView: state.sabFileBufView,
readOnly: create
? false : (state.sq3Codes.SQLITE_OPEN_READONLY & flags),
deleteOnClose: deleteOnClose
});
__openFiles[fid] = fobj;
fobj.filenameAbs = filename;
fobj.filenamePart = filenamePart;
fobj.dirHandle = hDir;
fobj.fileHandle = hFile;
fobj.sabView = state.sabFileBufView;
fobj.readOnly = create ? false : (state.sq3Codes.SQLITE_OPEN_READONLY & flags);
fobj.deleteOnClose = deleteOnClose;
storeAndNotify(opName, 0);
}catch(e){
wTimeEnd();
@ -354,7 +373,7 @@ const vfsAsyncImpls = {
try{
const fh = __openFiles[fid];
wTimeStart('xRead');
const nRead = fh.accessHandle.read(
const nRead = (await getSyncHandle(fh)).read(
fh.sabView.subarray(0, n),
{at: Number(offset)}
);
@ -395,7 +414,7 @@ const vfsAsyncImpls = {
wTimeStart('xTruncate');
try{
affirmNotRO('xTruncate', fh);
await fh.accessHandle.truncate(size);
await (await getSyncHandle(fh)).truncate(size);
}catch(e){
error("xTruncate():",e,fh);
state.s11n.storeException(2,e);
@ -413,8 +432,9 @@ const vfsAsyncImpls = {
const fh = __openFiles[fid];
affirmNotRO('xWrite', fh);
rc = (
n === fh.accessHandle.write(fh.sabView.subarray(0, n),
{at: Number(offset)})
n === (await getSyncHandle(fh))
.write(fh.sabView.subarray(0, n),
{at: Number(offset)})
) ? 0 : state.sq3Codes.SQLITE_IOERR_WRITE;
}catch(e){
error("xWrite():",e,fh);