}/*oo1 object*/;
if( self.window===self && 0!==capi.sqlite3_vfs_find('kvvfs') ){
- /* In the main window thread, add a couple of convenience proxies
- for localStorage and sessionStorage DBs... */
- let klass = sqlite3.oo1.LocalStorageDb = function(){
- dbCtorHelper.call(this, 'local', 'c', 'kvvfs');
- };
- klass.prototype = DB.prototype;
-
- klass = sqlite3.oo1.SessionStorageDb = function(){
- dbCtorHelper.call(this, 'session', 'c', 'kvvfs');
+ /* Features specific to kvvfs... */
+ /**
+ Clears all storage used by the kvvfs DB backend, deleting any
+ DB(s) stored there. Its argument must be either 'session',
+ 'local', or ''. In the first two cases, only sessionStorage
+ resp. localStorage is cleared. If it's an empty string (the
+ default) then both are cleared. Only storage keys which match
+ the pattern used by kvvfs are cleared: any other client-side
+ data are retained.
+ */
+ DB.clearKvvfsStorage = function(which=''){
+ const prefix = 'kvvfs-'+which;
+ const stores = [];
+ if('session'===which || ''===which) stores.push(sessionStorage);
+ if('local'===which || ''===which) stores.push(localStorage);
+ stores.forEach(function(s){
+ const toRm = [];
+ let i = 0, k;
+ for( i = 0; (k = s.key(i)); ++i ){
+ if(k.startsWith(prefix)) toRm.push(k);
+ }
+ toRm.forEach((kk)=>s.removeItem(kk));
+ });
};
- klass.prototype = DB.prototype;
- }
+ }/* main-window-only bits */
});
<div class="emscripten">
<progress value="0" max="100" id="module-progress" hidden='1'></progress>
</div><!-- /emscripten bits -->
- <div>Everything on this page happens in the dev console. TODOs for this demo include,
- but are not necessarily limited to:
-
- <ul>
- <li>UI controls to switch between localStorage and sessionStorage</li>
- <li>Button to clear storage.</li>
- <li>Button to dump the current db contents.</li>
- <!--li></li-->
- </ul>
- </div>
- <hr>
+ <fieldset>
+ <legend>Options</legend>
+ <div class='toolbar'>
+ <button id='btn-clear-log'>Clear log</button>
+ <button id='btn-clear-storage'>Clear storage</button>
+ <button id='btn-init-db'>(Re)init db</button>
+ <button id='btn-select1'>Select db rows</button>
+ </div>
+ </fieldset>
<div id='test-output'></div>
+ <style>
+ .toolbar {
+ display: flex;
+ }
+ .toolbar > * { margin: 0.25em; }
+ fieldset { border-radius: 0.5em; }
+ </style>
<script src="sqlite3-kvvfs.js"></script>
<script src="common/SqliteTestUtil.js"></script>
<script src="kvvfs1.js"></script>
const toss = function(...args){throw new Error(args.join(' '))};
const debug = console.debug.bind(console);
const eOutput = document.querySelector('#test-output');
- const log = console.log.bind(console)
- const logHtml = function(...args){
- log.apply(this, args);
+ const logC = console.log.bind(console)
+ const logE = function(domElement){
+ eOutput.append(domElement);
+ };
+ const logHtml = function(cssClass,...args){
const ln = document.createElement('div');
+ if(cssClass) ln.classList.add(cssClass);
ln.append(document.createTextNode(args.join(' ')));
- eOutput.append(ln);
+ logE(ln);
+ }
+ const log = function(...args){
+ logC(...args);
+ logHtml('',...args);
+ };
+ const warn = function(...args){
+ logHtml('warning',...args);
+ };
+ const error = function(...args){
+ logHtml('error',...args);
};
const runTests = function(Module){
oo = sqlite3.oo1,
wasm = capi.wasm;
log("Loaded module:",capi.sqlite3_libversion(), capi.sqlite3_sourceid());
- log("Build options:",wasm.compileOptionUsed());
T.assert( 0 !== capi.sqlite3_vfs_find(null) );
-
+ if(!oo.DB.clearKvvfsStorage){
+ warn("This build is not kvvfs-capable.");
+ return;
+ }
+
const dbStorage = 1 ? ':sessionStorage:' : ':localStorage:';
+ const theStore = 's'===dbStorage[1] ? sessionStorage : localStorage;
/**
The names ':sessionStorage:' and ':localStorage:' are handled
via the DB class constructor, not the C level. In the C API,
names for those keys, but that is subject to change.
*/
const db = new oo.DB( dbStorage );
- log("Storage backend:",db.filename /* note that the name was internally translated */);
- try {
- db.exec("create table if not exists t(a)");
- if(undefined===db.selectValue("select a from t limit 1")){
- log("New db. Populating. This DB will persist across page reloads.");
- db.exec("insert into t(a) values(1),(2),(3)");
- }else{
- log("Found existing table data:");
+
+ document.querySelector('#btn-clear-storage').addEventListener('click',function(){
+ oo.DB.clearKvvfsStorage();
+ log("kvvfs localStorage and sessionStorage cleared.");
+ });
+ document.querySelector('#btn-clear-log').addEventListener('click',function(){
+ eOutput.innerText = '';
+ });
+ document.querySelector('#btn-init-db').addEventListener('click',function(){
+ const saveSql = [];
+ try{
+ db.exec({
+ sql:["drop table if exists t;",
+ "create table if not exists t(a);",
+ "insert into t(a) values(?),(?),(?)"],
+ bind: [performance.now() >> 0,
+ (performance.now() * 2) >> 0,
+ (performance.now() / 2) >> 0],
+ saveSql
+ });
+ console.log("saveSql =",saveSql,theStore);
+ log("DB (re)initialized.");
+ }catch(e){
+ error(e.message);
+ }
+ });
+ const btnSelect = document.querySelector('#btn-select1');
+ btnSelect.addEventListener('click',function(){
+ log("DB rows:");
+ try{
db.exec({
sql: "select * from t order by a",
rowMode: 0,
- callback: function(v){log(v)}
+ callback: (v)=>log(v)
});
+ }catch(e){
+ error(e.message);
}
- }finally{
- db.close();
+ });
+ log("Storage backend:",db.filename /* note that the name was internally translated */);
+ if(0===db.selectValue('select count(*) from sqlite_master')){
+ log("DB is empty. Use the init button to populate it.");
+ }else{
+ log("DB contains data from a previous session. Use the Clear Ctorage button to delete it.");
+ btnSelect.click();
}
- log("End of demo.");
};
sqlite3InitModule(self.sqlite3TestModule).then(function(theModule){
-C Merge\skv-vfs\sbranch\sinto\sfiddle-opfs\sbranch\sto\sadd\skvvfs-based\swasm\sbuild\sand\sdemo.
-D 2022-09-12T16:09:50.625
+C Add\ssqlite3.oo1.DB.clearKvvfsStorage().\sAdd\scontrols\sto\skvvfs1.js\sdemo\sto\sreset\sand\squery\sthe\sdb\swithout\srequiring\sthe\sdev\sconsole.
+D 2022-09-12T17:59:04.237
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/wasm/api/post-js-header.js 0e853b78db83cb1c06b01663549e0e8b4f377f12f5a2d9a4a06cb776c003880b
F ext/wasm/api/sqlite3-api-cleanup.js 101919ec261644e2f6f0a59952fd9612127b69ea99b493277b2789ea478f9b6b
F ext/wasm/api/sqlite3-api-glue.js 2bf536a38cde324cf352bc2c575f8e22c6d204d667c0eda5a254ba45318914bc
-F ext/wasm/api/sqlite3-api-oo1.js a9d8892be246548a9978ace506d108954aa13eb5ce25332975c8377953804ff3
+F ext/wasm/api/sqlite3-api-oo1.js b498662748918c132aa59433ea2bd2ebb7e026549fd68506a1ae1ea94736f4f6
F ext/wasm/api/sqlite3-api-opfs.js 011799db398157cbd254264b6ebae00d7234b93d0e9e810345f213a5774993c0
F ext/wasm/api/sqlite3-api-prologue.js 9e37ce4dfd74926d0df80dd7e72e33085db4bcee48e2c21236039be416a7dff2
F ext/wasm/api/sqlite3-api-worker1.js d33062afa045fd4be01ba4abc266801807472558b862b30056211b00c9c347b4
F ext/wasm/jaccwabyt/jaccwabyt_test.c 39e4b865a33548f943e2eb9dd0dc8d619a80de05d5300668e9960fff30d0d36f
F ext/wasm/jaccwabyt/jaccwabyt_test.exports 5ff001ef975c426ffe88d7d8a6e96ec725e568d2c2307c416902059339c06f19
F ext/wasm/kvvfs.make dba616578bf91a76370a46494dd68a09c6dff5beb6d5561e2db65a27216e9630
-F ext/wasm/kvvfs1.html b8304cd5c7e7ec32c3b15521a95c322d6efdb8d22b3c4156123545dc54e07583
-F ext/wasm/kvvfs1.js a5075f98ffecd7d32348697db991fc61342d89aa20651034d1572af61890fb8b
+F ext/wasm/kvvfs1.html 83bac238d1e93ed102a461672fc58fe74e611e426708e9a5c66002c01eadb942
+F ext/wasm/kvvfs1.js 53721a42e0ec45f6978cc723e5de47f882517867d0fcff4c6ff05f4c422e27c4
F ext/wasm/scratchpad-opfs-main.html 4565cf194e66188190d35f70e82553e2e2d72b9809b73c94ab67b8cfd14d2e0c
F ext/wasm/scratchpad-opfs-main.js 69e960e9161f6412fd0c30f355d4112f1894d6609eb431e2d16d207d1380518e
F ext/wasm/scratchpad-opfs-worker.html 66c1d15d678f3bd306373d76b61c6c8aef988f61f4a8dd40185d452f9c6d2bf5
F src/os_kv.c a188e92dac693b1c1b512d93b0c4dc85c1baad11e322b01121f87057996e4d11
F src/os_setup.h 0711dbc4678f3ac52d7fe736951b6384a0615387c4ba5135a4764e4e31f4b6a6
F src/os_unix.c d6322b78130d995160bb9cfb7850678ad6838b08c1d13915461b33326a406c04
-F src/os_win.c e9454cb141908e8eef2102180bad353a36480612d5b736e4c2bd5777d9b25a34
+F src/os_win.c 8d129ae3e59e0fa900e20d0ad789e96f2e08177f0b00b53cdda65c40331e0902
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 6176d9752eb580419e8fef4592dc417a6b00ddfd43ee22f818819bf8840ceee8
F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
-F src/pcache.c 22a6ebe498d1d26c85fd1e3bcb246d97b882c060027c1e1688fbea905f5ac3cf
+F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
-F src/pcache1.c 849a26ea9dc1e6a176b75dc576672a598170b0b46aeef87a981dd25e0af0ccf9
+F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
F src/pragma.c 9bf7d8a2a9ad3bc36df3ec0d61817a44c38a1da527d59c26c203047f906e334a
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 971d5819a4bda88038c2283d71fc0a2974ffc3dd480f9bd941341017abacfd1b
F tool/showwal.c 0253c187ae16fdae9cde89e63e1dfcd3bb35e5416d066415f99e2f8cac6ab03d
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl 1b5be34c6223cb1af06da2a10fb77863eb869b1962d055820b0a11cf2336ab45
-F tool/speed-check.sh ff74a68bb95a0341275f4d3c9a7d8a3800bd278aceecf1913295a1f0175bc3e6
+F tool/speed-check.sh 13f8e07dbfe25f3aecda33fb6068894665af61ca1360a7b654be0ad0c3f3ae0b
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 4e6ce329872eb733ba2f7f7879747c52761ae97790fd8ed169a25a79854cc3d9 e49682c5eac91958f143e639c5656ca54560d14f5805d514bf4aa0c206e63844
-R f15733833cf5e73dce86b4365f218581
+P a7d8b26acd3c1ae344369e4d70804c0cab45272c0983cfd32d616a0a7b28acb9
+R 984d02350bb7056e7ff7dbf797b44085
U stephan
-Z f2a01bf4c99986993a2e00b39e93be73
+Z f41406c18c315f5b1f10f4c607ad1f16
# Remove this line to create a well-formed Fossil manifest.
-a7d8b26acd3c1ae344369e4d70804c0cab45272c0983cfd32d616a0a7b28acb9
\ No newline at end of file
+d845c6c22bd5d3fffc66e0566df346d690dd8bd1fc1688e312161b1a1edcfd79
\ No newline at end of file
char *zFull /* Output buffer */
){
int rc;
- sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR);
+ MUTEX_LOGIC( sqlite3_mutex *pMutex; )
+ MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); )
sqlite3_mutex_enter(pMutex);
rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
sqlite3_mutex_leave(pMutex);
assert( sqlite3PcachePageSanity(p) );
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
- sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
if( pOther ){
- PgHdr *pPg = (PgHdr*)pOther->pExtra;
- pPg->pgno = p->pgno;
- if( pPg->pPage==0 ){
- sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pOther, 0);
- }
+ PgHdr *pXPage = (PgHdr*)pOther->pExtra;
+ assert( pXPage->nRef==0 );
+ pXPage->nRef++;
+ pCache->nRefSum++;
+ sqlite3PcacheDrop(pXPage);
}
+ sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
p->pgno = newPgno;
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
assert( iOld!=iNew ); /* The page number really is changing */
pcache1EnterMutex(pCache->pGroup);
-
+
assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
hOld = iOld%pCache->nHash;
pp = &pCache->apHash[hOld];
}
*pp = pPage->pNext;
+ assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
hNew = iNew%pCache->nHash;
- pp = &pCache->apHash[hNew];
- while( *pp ){
- if( (*pp)->iKey==iNew ){
- /* If there is already another pcache entry at iNew, change it to iOld,
- ** thus swapping the positions of iNew and iOld */
- PgHdr1 *pOld = *pp;
- *pp = pOld->pNext;
- pOld->pNext = pCache->apHash[hOld];
- pCache->apHash[hOld] = pOld;
- pOld->iKey = iOld;
- break;
- }else{
- pp = &(*pp)->pNext;
- }
- }
-
pPage->iKey = iNew;
pPage->pNext = pCache->apHash[hNew];
pCache->apHash[hNew] = pPage;
--cachesize)
shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1"
;;
+ --stmtcache)
+ shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtcache $1"
+ ;;
--checkpoint)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --checkpoint"
;;
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset rtree"
CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_RTREE"
;;
+ --persist)
+ SPEEDTEST_OPTS="$SPEEDTEST_OPTS --persist"
+ ;;
--orm)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset orm"
;;