Using a VFS shim together with another user-specified VFS
(1) By Aloys (aloys) on 2020-06-29 11:36:55 [link] [source]
I know that it is possible to register a new default VFS, which is in my case a VFS shim forwarding all VFS commands to the previous default VFS, but performing some additional actions.
However, a user can overwrite the default VFS by specifying the parameter "vfs=" in the URI on opening a database.
What I want to accomplish now, is to respect the "vfs=" parameter, but adding the special VFS shim on top of the user-specified VFS nevertheless. Is that somehow possible? How could that be accomplished?
Thanks for any hints.
(2) By Larry Brasfield (LarryBrasfield) on 2020-06-29 13:53:20 in reply to 1 [link] [source]
You can stack shims as deep as you like, perhaps limited by liking performance. To see how, you should study "section 3.4. VFS Shims" and probably the code it references.
(3) By Aloys (aloys) on 2020-06-29 16:55:16 in reply to 2 [source]
Well, I know that vfs shims can be nested. However, the problem here is that if a user specifies a different vfs using the vfs URI parameter, the parameter is handled by SQLite internally.
For example, if "vfstrace" is enabled in the SQLite shell, the tracing vfs shim is set as the default vfs, typically using the previous default vfs as the underlying vfs. However, if the user now uses the vfs URI parameter to select a different vfs, e.g. "unix-excl", tracing will no longer occur.
My question is whether there is a way to let the user select a vfs via URI, but still keep the vfs shim enabled. In the example, the effect should be that "trace" vfs shim uses "unix-excl" as the underlying vfs, if the user specifies the URI parameter "vfs=unix-excl". Currently, "unix-excl" would be used without "trace".
(4.2) By David Jones (vman59) on 2020-06-29 18:40:27 edited from 4.1 in reply to 1 [link] [source]
I'd try getting the address of the target VFS, unregistering it, clone your shim VFS and change the name and forwarding VFS, then register your clone. When the user specifes the original VFS name in a URI, sqlite3_find_vfs will then return the clone of your shim. If you have to deal with users loading extensions, you'd also have to hijack the vfs register method in the external API.
(5) By Aloys (aloys) on 2020-06-29 20:11:15 in reply to 4.2 [link] [source]
Thanks, David, for the sketch how the problem could be possibly tackled.
The approach sounds rather tricky, especially, if a user has several database connections open, possibly using different VFSes. If I understood it correctly, the VFS names need to be unique. That is, I would have to create a clone of the VFS shim with a different name for each different underlying VFS.
The main problem I see is that I would have to create VFS shim clones for all potential underlying VFSes in advance, because the SQLite code analyzing the URI parameters already calls
sqlite3_vfs_find. And this can't be easily intercepted.
I get the impression that this approach isn't going to work in the general case, when I do not know in advance which underlying VFSes the user might want to use.
(6) By David Jones (vman59) on 2020-06-29 22:21:46 in reply to 5 [link] [source]
You don't need unique names. You unregister the original VFS (putting its VFS object in a private list), them give your shim clone the same name before registering it. I keep thinking there is a supported way to get the list of all current VFS's, but it escapes me right now.
(7) By Aloys (aloys) on 2020-06-30 09:59:40 in reply to 6 [link] [source]
You don't need unique names.
I doubt that that is true. The registered VFSes are members of a linked list, and function
sqlite3_vfs_find uses this list to identify a VFS by name. If you have 2 or more VFSes with the same name, only the first in the list can be found.
You unregister the original VFS (putting its VFS object in a private list), then give your shim clone the same name before registering it.
Ok, if the original VFS is no longer registered this will work. However, if there are other VFS shims involved, things could possibly become nasty.
I keep thinking there is a supported way to get the list of all current VFS's, but it escapes me right now.
The SQLite shell command
vfslist allows to walk through the list of registered VFSes.
It seems that all sorts of automatism in combining a VFS shim with existing VFSes could lead to weird effects. Most likely I will be better off to allow a user/developer to explicitly combine my VFS shim with a certain other underlying VFS and assign a new name of his/her choice to the combined VFS.