Skip to content

Commit 0555bdd

Browse files
committed
libsql-sqlite3: Optimize pager codec check more
Checking if we have a custom codec at pager open time is still plenty slow. Change the check to happen at database open time instead.
1 parent 5379778 commit 0555bdd

File tree

14 files changed

+153
-82
lines changed

14 files changed

+153
-82
lines changed

libsql-ffi/bundled/SQLite3MultipleCiphers/src/codecext.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
*/
99

1010
/*
11-
** Forward declaration for pager codec cache update function.
12-
** This should be called after encryption is added, removed, or changed.
11+
** Forward declaration for db codec check function.
12+
** Used to update cached codec status after encryption changes.
1313
*/
14-
void libsql_pager_update_codec_cache(struct Pager *pPager);
14+
int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename);
1515

1616
/*
1717
** "Special" version of function sqlite3BtreeSetPageSize
@@ -591,8 +591,8 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey)
591591
{
592592
sqlite3mcSetIsEncrypted(codec, 0);
593593
}
594-
/* Update the pager's cached codec status after changing encryption */
595-
libsql_pager_update_codec_cache(pPager);
594+
/* Update both pager and database cached codec status after changing encryption */
595+
db->aDb[dbIndex].hasCodec = pPager->hasCodec = libsql_db_has_codec(pPager->pVfs, pPager->zFilename);
596596
}
597597
else
598598
{

libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16436,7 +16436,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
1643616436
int,
1643716437
int,
1643816438
int,
16439-
void(*)(DbPage*)
16439+
void(*)(DbPage*),
16440+
int /* hasCodec from connection-level cache */
1644016441
);
1644116442
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
1644216443
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
@@ -16625,7 +16626,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
1662516626
sqlite3 *db, /* Associated database connection */
1662616627
Btree **ppBtree, /* Return open Btree* here */
1662716628
int flags, /* Flags */
16628-
int vfsFlags /* Flags passed through to VFS open */
16629+
int vfsFlags, /* Flags passed through to VFS open */
16630+
int hasCodec /* True if this database has encryption codec */
1662916631
);
1663016632

1663116633
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
@@ -17993,6 +17995,7 @@ struct Db {
1799317995
Btree *pBt; /* The B*Tree structure for this database file */
1799417996
u8 safety_level; /* How aggressive at syncing data to disk */
1799517997
u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
17998+
u8 hasCodec; /* True if this database has encryption codec */
1799617999
Schema *pSchema; /* Pointer to database schema (possibly shared) */
1799718000
};
1799818001

@@ -58232,27 +58235,18 @@ struct Pager {
5823258235
/* libSQL extension: pager codec */
5823358236

5823458237
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
58235-
int libsql_pager_has_codec_impl(struct Pager *_p);
5823658238
int libsql_pager_codec_impl(libsql_pghdr *hdr, void **ret);
58239+
int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename);
5823758240
#endif
5823858241

5823958242
int libsql_pager_has_codec(struct Pager *_p) {
5824058243
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
58241-
return libsql_pager_has_codec_impl(_p);
58244+
return libsql_db_has_codec(_p->pVfs, _p->zFilename);
5824258245
#else
5824358246
return 0;
5824458247
#endif
5824558248
}
5824658249

58247-
/*
58248-
** Update the cached codec status.
58249-
** This should be called after encryption is added, removed, or changed
58250-
** via sqlite3_rekey_v2() to ensure the cached hasCodec value is correct.
58251-
*/
58252-
void libsql_pager_update_codec_cache(struct Pager *pPager) {
58253-
pPager->hasCodec = libsql_pager_has_codec(pPager);
58254-
}
58255-
5825658250
int libsql_pager_codec(libsql_pghdr *hdr, void **ret) {
5825758251
if (!ret) {
5825858252
return SQLITE_MISUSE_BKPT;
@@ -62295,7 +62289,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
6229562289
int nExtra, /* Extra bytes append to each in-memory page */
6229662290
int flags, /* flags controlling this file */
6229762291
int vfsFlags, /* flags passed through to sqlite3_vfs.xOpen() */
62298-
void (*xReinit)(DbPage*) /* Function to reinitialize pages */
62292+
void (*xReinit)(DbPage*),/* Function to reinitialize pages */
62293+
int dbHasCodec /* hasCodec from connection-level cache */
6229962294
){
6230062295
u8 *pPtr;
6230162296
Pager *pPager = 0; /* Pager object to allocate and return */
@@ -62635,8 +62630,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
6263562630
/* pPager->xBusyHandler = 0; */
6263662631
/* pPager->pBusyHandlerArg = 0; */
6263762632
pPager->xReiniter = xReinit;
62638-
/* Cache the codec check result to avoid expensive VFS stack traversal on every page read */
62639-
pPager->hasCodec = libsql_pager_has_codec(pPager);
62633+
/* Use cached codec status from connection level to avoid expensive VFS stack traversal
62634+
** and file lookup on every pager initialization */
62635+
pPager->hasCodec = dbHasCodec;
6264062636
setGetterMethod(pPager);
6264162637
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
6264262638
/* pPager->szMmap = SQLITE_DEFAULT_MMAP_SIZE // will be set by btree.c */
@@ -73757,7 +73753,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
7375773753
sqlite3 *db, /* Associated database handle */
7375873754
Btree **ppBtree, /* Pointer to new Btree object written here */
7375973755
int flags, /* Options */
73760-
int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
73756+
int vfsFlags, /* Flags passed through to sqlite3_vfs.xOpen() */
73757+
int hasCodec /* True if this database has encryption codec */
7376173758
){
7376273759
BtShared *pBt = 0; /* Shared part of btree structure */
7376373760
Btree *p; /* Handle to return */
@@ -73902,7 +73899,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
7390273899
goto btree_open_out;
7390373900
}
7390473901
rc = sqlite3PagerOpen(pVfs, db->wal_manager ,&pBt->pPager, zFilename,
73905-
sizeof(MemPage), flags, vfsFlags, pageReinit);
73902+
sizeof(MemPage), flags, vfsFlags, pageReinit, hasCodec);
7390673903
if( rc==SQLITE_OK ){
7390773904
sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
7390873905
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@@ -98769,7 +98766,8 @@ case OP_OpenEphemeral: { /* ncycle */
9876998766
pCx->isEphemeral = 1;
9877098767
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx,
9877198768
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
98772-
vfsFlags);
98769+
vfsFlags,
98770+
0); /* Ephemeral tables are never encrypted */
9877398771
if( rc==SQLITE_OK ){
9877498772
rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0);
9877598773
if( rc==SQLITE_OK ){
@@ -121888,6 +121886,10 @@ int libsql_handle_extra_attach_params(sqlite3* db, const char* zName, const char
121888121886
SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);
121889121887
#endif
121890121888

121889+
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
121890+
int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename);
121891+
#endif
121892+
121891121893
/*
121892121894
** An SQL user-function registered to do the work of an ATTACH statement. The
121893121895
** three arguments to the function come directly from an attach statement:
@@ -121940,7 +121942,8 @@ static void attachFunc(
121940121942
Btree *pNewBt = 0;
121941121943
pVfs = sqlite3_vfs_find("memdb");
121942121944
if( pVfs==0 ) return;
121943-
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB);
121945+
rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNewBt, 0, SQLITE_OPEN_MAIN_DB,
121946+
0); /* Memdb databases are never encrypted */
121944121947
if( rc==SQLITE_OK ){
121945121948
Schema *pNewSchema = sqlite3SchemaGet(db, pNewBt);
121946121949
if( pNewSchema ){
@@ -122009,7 +122012,13 @@ static void attachFunc(
122009122012
}
122010122013
assert( pVfs );
122011122014
flags |= SQLITE_OPEN_MAIN_DB;
122012-
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
122015+
/* Check encryption status for this database file */
122016+
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
122017+
pNew->hasCodec = libsql_db_has_codec(pVfs, zPath);
122018+
#else
122019+
pNew->hasCodec = 0;
122020+
#endif
122021+
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags, pNew->hasCodec);
122013122022
db->nDb++;
122014122023
pNew->zDbSName = sqlite3DbStrDup(db, zName);
122015122024
}
@@ -128047,7 +128056,8 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
128047128056
SQLITE_OPEN_DELETEONCLOSE |
128048128057
SQLITE_OPEN_TEMP_DB;
128049128058

128050-
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
128059+
db->aDb[1].hasCodec = 0; /* Temp databases are never encrypted */
128060+
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags, db->aDb[1].hasCodec);
128051128061
if( rc!=SQLITE_OK ){
128052128062
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
128053128063
"file for storing temporary tables");
@@ -184304,6 +184314,10 @@ static const char *uriParameter(const char *zFilename, const char *zParam){
184304184314
int libsql_handle_extra_uri_params(sqlite3 *db, const char *zOpen);
184305184315
#endif
184306184316

184317+
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
184318+
int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename);
184319+
#endif
184320+
184307184321
/*
184308184322
** This routine does the work of opening a database on behalf of
184309184323
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
@@ -184559,9 +184573,17 @@ static int openDatabase(
184559184573
}
184560184574
#endif
184561184575

184576+
/* Cache encryption status at database open time to avoid expensive
184577+
** VFS stack traversal and file lookup on every pager initialization */
184578+
#ifdef LIBSQL_CUSTOM_PAGER_CODEC
184579+
db->aDb[0].hasCodec = libsql_db_has_codec(db->pVfs, zOpen);
184580+
#else
184581+
db->aDb[0].hasCodec = 0;
184582+
#endif
184583+
184562184584
/* Open the backend database driver */
184563184585
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
184564-
flags | SQLITE_OPEN_MAIN_DB);
184586+
flags | SQLITE_OPEN_MAIN_DB, db->aDb[0].hasCodec);
184565184587
if( rc!=SQLITE_OK ){
184566184588
if( rc==SQLITE_IOERR_NOMEM ){
184567184589
rc = SQLITE_NOMEM_BKPT;

libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3mc_vfs.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,13 +1347,18 @@ sqlite3mcCheckVfs(const char* zVfs)
13471347
return rc;
13481348
}
13491349

1350-
int libsql_pager_has_codec_impl(struct Pager* pPager)
1350+
/*
1351+
** Check if a database file is encrypted at connection open time.
1352+
** This checks both the VFS stack and the specific file encryption status.
1353+
** The result is cached at the connection level to avoid expensive checks
1354+
** on every pager initialization.
1355+
*/
1356+
int libsql_db_has_codec(sqlite3_vfs* pVfs, const char* zFilename)
13511357
{
13521358
int hasCodec = 0;
13531359
sqlite3mc_vfs* pVfsMC = NULL;
1354-
sqlite3_vfs* pVfs = pPager->pVfs;
13551360

1356-
/* Check whether the VFS stack of the pager contains a Multiple Ciphers VFS */
1361+
/* Check whether the VFS stack contains a Multiple Ciphers VFS */
13571362
for (; pVfs; pVfs = pVfs->pNext)
13581363
{
13591364
if (pVfs && pVfs->xOpen == mcVfsOpen)
@@ -1367,7 +1372,7 @@ int libsql_pager_has_codec_impl(struct Pager* pPager)
13671372
/* Check whether codec is enabled for associated database file */
13681373
if (pVfsMC)
13691374
{
1370-
sqlite3mc_file* mcFile = mcFindDbMainFileName(pVfsMC, pPager->zFilename);
1375+
sqlite3mc_file* mcFile = mcFindDbMainFileName(pVfsMC, zFilename);
13711376
if (mcFile)
13721377
{
13731378
Codec* codec = mcFile->codec;

0 commit comments

Comments
 (0)