Skip to content

Commit 9fd21f4

Browse files
committed
Remove global VFS management structure
Attempt to solve issue #73: global VFS management structure did not work properly in multi-threaded environment.
1 parent 2249ca3 commit 9fd21f4

File tree

3 files changed

+93
-60
lines changed

3 files changed

+93
-60
lines changed

src/codecext.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
** Purpose: Implementation of SQLite codec API
44
** Author: Ulrich Telle
55
** Created: 2006-12-06
6-
** Copyright: (c) 2006-2021 Ulrich Telle
6+
** Copyright: (c) 2006-2022 Ulrich Telle
77
** License: MIT
88
*/
99

@@ -167,7 +167,7 @@ SQLITE_PRIVATE Codec*
167167
sqlite3mcGetMainCodec(sqlite3* db);
168168

169169
SQLITE_PRIVATE void
170-
sqlite3mcSetCodec(sqlite3* db, const char* zFileName, Codec* codec);
170+
sqlite3mcSetCodec(sqlite3* db, const char* zDbName, const char* zFileName, Codec* codec);
171171

172172
static int
173173
mcAdjustBtree(Btree* pBt, int nPageSize, int nReserved, int isLegacy)
@@ -229,7 +229,7 @@ sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey,
229229
sqlite3mcSetBtree(codec, db->aDb[nDb].pBt);
230230
mcAdjustBtree(db->aDb[nDb].pBt, pageSize, reserved, sqlite3mcGetLegacyWriteCipher(codec));
231231
sqlite3mcCodecSizeChange(codec, pageSize, reserved);
232-
sqlite3mcSetCodec(db, dbFileName, codec);
232+
sqlite3mcSetCodec(db, zDbName, dbFileName, codec);
233233
}
234234
else
235235
{
@@ -250,7 +250,7 @@ sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey,
250250
/* Remove codec for main database */
251251
if (nDb == 0 && nKey == 0)
252252
{
253-
sqlite3mcSetCodec(db, dbFileName, NULL);
253+
sqlite3mcSetCodec(db, zDbName, dbFileName, NULL);
254254
}
255255
}
256256
}
@@ -285,7 +285,7 @@ sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey,
285285
int reserved = sqlite3mcGetReservedWriteCipher(codec);
286286
mcAdjustBtree(db->aDb[nDb].pBt, pageSize, reserved, sqlite3mcGetLegacyWriteCipher(codec));
287287
sqlite3mcCodecSizeChange(codec, pageSize, reserved);
288-
sqlite3mcSetCodec(db, dbFileName, codec);
288+
sqlite3mcSetCodec(db, zDbName, dbFileName, codec);
289289
}
290290
else
291291
{
@@ -432,7 +432,7 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey)
432432
int nReservedWriteCipher;
433433
sqlite3mcSetHasReadCipher(codec, 0); /* Original database is not encrypted */
434434
mcAdjustBtree(pBt, sqlite3mcGetPageSizeWriteCipher(codec), sqlite3mcGetReservedWriteCipher(codec), sqlite3mcGetLegacyWriteCipher(codec));
435-
sqlite3mcSetCodec(db, dbFileName, codec);
435+
sqlite3mcSetCodec(db, zDbName, dbFileName, codec);
436436
nReservedWriteCipher = sqlite3mcGetReservedWriteCipher(codec);
437437
sqlite3mcCodecSizeChange(codec, nPagesize, nReservedWriteCipher);
438438
if (nReserved != nReservedWriteCipher)
@@ -583,7 +583,7 @@ sqlite3_rekey_v2(sqlite3* db, const char* zDbName, const void* zKey, int nKey)
583583
if (!sqlite3mcIsEncrypted(codec))
584584
{
585585
/* Remove codec for unencrypted database */
586-
sqlite3mcSetCodec(db, dbFileName, NULL);
586+
sqlite3mcSetCodec(db, zDbName, dbFileName, NULL);
587587
}
588588
return rc;
589589
}

src/sqlite3mc_version.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
#define SQLITE3MC_VERSION_H_
1414

1515
#define SQLITE3MC_VERSION_MAJOR 1
16-
#define SQLITE3MC_VERSION_MINOR 3
17-
#define SQLITE3MC_VERSION_RELEASE 10
16+
#define SQLITE3MC_VERSION_MINOR 4
17+
#define SQLITE3MC_VERSION_RELEASE 0
1818
#define SQLITE3MC_VERSION_SUBRELEASE 0
19-
#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.3.10"
19+
#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.4.0"
2020

2121
#endif /* SQLITE3MC_VERSION_H_ */

src/sqlite3mc_vfs.c

Lines changed: 83 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
** Purpose: Implementation of SQLite VFS for Multiple Ciphers
44
** Author: Ulrich Telle
55
** Created: 2020-02-28
6-
** Copyright: (c) 2020-2021 Ulrich Telle
6+
** Copyright: (c) 2020-2022 Ulrich Telle
77
** License: MIT
88
*/
99

@@ -29,6 +29,7 @@ struct sqlite3mc_file
2929
{
3030
sqlite3_file base; /* sqlite3_file I/O methods */
3131
sqlite3_file* pFile; /* Real underlying OS file */
32+
sqlite3mc_vfs* pVfsMC; /* Pointer to the sqlite3mc_vfs object */
3233
const char* zFileName; /* File name */
3334
int openFlags; /* Open flags */
3435
sqlite3mc_file* pMainNext; /* Next main db file */
@@ -51,9 +52,6 @@ struct sqlite3mc_vfs
5152
#define REALVFS(p) ((sqlite3_vfs*)(((sqlite3mc_vfs*)(p))->base.pAppData))
5253
#define REALFILE(p) (((sqlite3mc_file*)(p))->pFile)
5354

54-
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
55-
#define ORIGFILE(p) ((sqlite3_file*)(((CksmFile*)(p))+1))
56-
5755
/*
5856
** Prototypes for VFS methods
5957
*/
@@ -107,37 +105,8 @@ static const int walFrameHeaderSize = 24;
107105
static const int walFileHeaderSize = 32;
108106

109107
/*
110-
** Global VFS structure of SQLite3 Multiple Ciphers VFS
108+
** Global I/O method structure of SQLite3 Multiple Ciphers VFS
111109
*/
112-
static sqlite3mc_vfs mcVfsGlobal =
113-
{
114-
{
115-
3, /* iVersion */
116-
0, /* szOsFile */
117-
1024, /* mxPathname */
118-
0, /* pNext */
119-
SQLITE3MC_VFS_NAME, /* zName */
120-
0, /* pAppData */
121-
mcVfsOpen, /* xOpen */
122-
mcVfsDelete, /* xDelete */
123-
mcVfsAccess, /* xAccess */
124-
mcVfsFullPathname, /* xFullPathname */
125-
mcVfsDlOpen, /* xDlOpen */
126-
mcVfsDlError, /* xDlError */
127-
mcVfsDlSym, /* xDlSym */
128-
mcVfsDlClose, /* xDlClose */
129-
mcVfsRandomness, /* xRandomness */
130-
mcVfsSleep, /* xSleep */
131-
mcVfsCurrentTime, /* xCurrentTime */
132-
mcVfsGetLastError, /* xGetLastError */
133-
mcVfsCurrentTimeInt64, /* xCurrentTimeInt64 */
134-
mcVfsSetSystemCall, /* xSetSystemCall */
135-
mcVfsGetSystemCall, /* xGetSystemCall */
136-
mcVfsNextSystemCall /* xNextSystemCall */
137-
},
138-
NULL
139-
};
140-
141110
static sqlite3_io_methods mcIoMethodsGlobal =
142111
{
143112
3, /* iVersion */
@@ -171,10 +140,10 @@ static sqlite3_io_methods mcIoMethodsGlobal =
171140
static void mcMainListAdd(sqlite3mc_file* pFile)
172141
{
173142
assert( (pFile->openFlags & SQLITE_OPEN_MAIN_DB) );
174-
sqlite3_mutex_enter(mcVfsGlobal.mutex);
175-
pFile->pMainNext = mcVfsGlobal.pMain;
176-
mcVfsGlobal.pMain = pFile;
177-
sqlite3_mutex_leave(mcVfsGlobal.mutex);
143+
sqlite3_mutex_enter(pFile->pVfsMC->mutex);
144+
pFile->pMainNext = pFile->pVfsMC->pMain;
145+
pFile->pVfsMC->pMain = pFile;
146+
sqlite3_mutex_leave(pFile->pVfsMC->mutex);
178147
}
179148

180149
/*
@@ -183,11 +152,11 @@ static void mcMainListAdd(sqlite3mc_file* pFile)
183152
static void mcMainListRemove(sqlite3mc_file* pFile)
184153
{
185154
sqlite3mc_file** pMainPrev;
186-
sqlite3_mutex_enter(mcVfsGlobal.mutex);
187-
for (pMainPrev = &mcVfsGlobal.pMain; *pMainPrev && *pMainPrev != pFile; pMainPrev = &((*pMainPrev)->pMainNext)){}
155+
sqlite3_mutex_enter(pFile->pVfsMC->mutex);
156+
for (pMainPrev = &pFile->pVfsMC->pMain; *pMainPrev && *pMainPrev != pFile; pMainPrev = &((*pMainPrev)->pMainNext)){}
188157
if (*pMainPrev) *pMainPrev = pFile->pMainNext;
189158
pFile->pMainNext = 0;
190-
sqlite3_mutex_leave(mcVfsGlobal.mutex);
159+
sqlite3_mutex_leave(pFile->pVfsMC->mutex);
191160
}
192161

193162
/*
@@ -205,18 +174,68 @@ static sqlite3mc_file* mcFindDbMainFileName(sqlite3mc_vfs* mcVfs, const char* zF
205174
return pDb;
206175
}
207176

177+
/*
178+
** Find a pointer to the Multiple Ciphers VFS in use for a database connection.
179+
*/
180+
static sqlite3mc_vfs* mcFindVfs(sqlite3* db, const char* zDbName)
181+
{
182+
sqlite3mc_vfs* pVfsMC = NULL;
183+
if (db->pVfs && db->pVfs->xOpen == mcVfsOpen)
184+
{
185+
/* The top level VFS is a Multiple Ciphers VFS */
186+
pVfsMC = (sqlite3mc_vfs*)(db->pVfs);
187+
}
188+
else
189+
{
190+
/*
191+
** The top level VFS is not a Multiple Ciphers VFS.
192+
** Retrieve the VFS names stack.
193+
*/
194+
char* zVfsNameStack = 0;
195+
if ((sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsNameStack) == SQLITE_OK) && (zVfsNameStack != NULL))
196+
{
197+
/* Search for the name prefix of a Multiple Ciphers VFS. */
198+
char* zVfsName = strstr(zVfsNameStack, SQLITE3MC_VFS_NAME);
199+
if (zVfsName != NULL)
200+
{
201+
/* The prefix was found, now determine the full VFS name. */
202+
char* zVfsNameEnd = zVfsName + strlen(SQLITE3MC_VFS_NAME);
203+
if (*zVfsNameEnd == '-')
204+
{
205+
for (++zVfsNameEnd; *zVfsNameEnd != '/' && *zVfsNameEnd != 0; ++zVfsNameEnd);
206+
if (*zVfsNameEnd == '/') *zVfsNameEnd = 0;
207+
208+
/* Find a pointer to the VFS with the determined name. */
209+
sqlite3_vfs* pVfs = sqlite3_vfs_find(zVfsName);
210+
if (pVfs && pVfs->xOpen == mcVfsOpen)
211+
{
212+
pVfsMC = (sqlite3mc_vfs*) pVfs;
213+
}
214+
}
215+
}
216+
sqlite3_free(zVfsNameStack);
217+
}
218+
}
219+
return pVfsMC;
220+
}
221+
208222
/*
209223
** Find the codec of the database file
210224
** corresponding to the database schema name.
211225
*/
212226
SQLITE_PRIVATE Codec* sqlite3mcGetCodec(sqlite3* db, const char* zDbName)
213227
{
214228
Codec* codec = NULL;
215-
const char* dbFileName = sqlite3_db_filename(db, zDbName);
216-
sqlite3mc_file* pDbMain = mcFindDbMainFileName(&mcVfsGlobal, dbFileName);
217-
if (pDbMain)
229+
sqlite3mc_vfs* pVfsMC = mcFindVfs(db, zDbName);
230+
231+
if (pVfsMC)
218232
{
219-
codec = pDbMain->codec;
233+
const char* dbFileName = sqlite3_db_filename(db, zDbName);
234+
sqlite3mc_file* pDbMain = mcFindDbMainFileName(pVfsMC, dbFileName);
235+
if (pDbMain)
236+
{
237+
codec = pDbMain->codec;
238+
}
220239
}
221240
return codec;
222241
}
@@ -239,9 +258,14 @@ SQLITE_PRIVATE Codec* sqlite3mcGetMainCodec(sqlite3* db)
239258
** connection handle is actually valid, because the association between
240259
** connection handles and database file handles is not maintained properly.
241260
*/
242-
SQLITE_PRIVATE void sqlite3mcSetCodec(sqlite3* db, const char* zFileName, Codec* codec)
261+
SQLITE_PRIVATE void sqlite3mcSetCodec(sqlite3* db, const char* zDbName, const char* zFileName, Codec* codec)
243262
{
244-
sqlite3mc_file* pDbMain = mcFindDbMainFileName(&mcVfsGlobal, zFileName);
263+
sqlite3mc_file* pDbMain = NULL;
264+
sqlite3mc_vfs* pVfsMC = mcFindVfs(db, zDbName);
265+
if (pVfsMC)
266+
{
267+
pDbMain = mcFindDbMainFileName((sqlite3mc_vfs*)(db->pVfs), zFileName);
268+
}
245269
if (pDbMain)
246270
{
247271
Codec* prevCodec = pDbMain->codec;
@@ -310,6 +334,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
310334
sqlite3mc_vfs* mcVfs = (sqlite3mc_vfs*) pVfs;
311335
sqlite3mc_file* mcFile = (sqlite3mc_file*) pFile;
312336
mcFile->pFile = (sqlite3_file*) &mcFile[1];
337+
mcFile->pVfsMC = mcVfs;
313338
mcFile->openFlags = flags;
314339
mcFile->zFileName = zName;
315340
mcFile->codec = 0;
@@ -340,7 +365,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
340365
else if (flags & SQLITE_OPEN_MAIN_JOURNAL)
341366
{
342367
const char* dbFileName = sqlite3_filename_database(zName);
343-
mcFile->pMainDb = mcFindDbMainFileName(&mcVfsGlobal, dbFileName);
368+
mcFile->pMainDb = mcFindDbMainFileName(mcFile->pVfsMC, dbFileName);
344369
mcFile->zFileName = zName;
345370
SQLITE3MC_DEBUG_LOG("mcVfsOpen MAIN Journal: mcFile=%p fileName=%s dbFileName=%s\n", mcFile, mcFile->zFileName, dbFileName);
346371
}
@@ -355,7 +380,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
355380
else if (flags & SQLITE_OPEN_SUBJOURNAL)
356381
{
357382
const char* dbFileName = sqlite3_filename_database(zName);
358-
mcFile->pMainDb = mcFindDbMainFileName(&mcVfsGlobal, dbFileName);
383+
mcFile->pMainDb = mcFindDbMainFileName(mcFile->pVfsMC, dbFileName);
359384
mcFile->zFileName = zName;
360385
SQLITE3MC_DEBUG_LOG("mcVfsOpen SUB Journal: mcFile=%p fileName=%s dbFileName=%s\n", mcFile, mcFile->zFileName, dbFileName);
361386
}
@@ -371,7 +396,7 @@ static int mcVfsOpen(sqlite3_vfs* pVfs, const char* zName, sqlite3_file* pFile,
371396
else if (flags & SQLITE_OPEN_WAL)
372397
{
373398
const char* dbFileName = sqlite3_filename_database(zName);
374-
mcFile->pMainDb = mcFindDbMainFileName(&mcVfsGlobal, dbFileName);
399+
mcFile->pMainDb = mcFindDbMainFileName(mcFile->pVfsMC, dbFileName);
375400
mcFile->zFileName = zName;
376401
SQLITE3MC_DEBUG_LOG("mcVfsOpen WAL Journal: mcFile=%p fileName=%s dbFileName=%s\n", mcFile, mcFile->zFileName, dbFileName);
377402
}
@@ -1155,6 +1180,14 @@ static int mcIoFileControl(sqlite3_file* pFile, int op, void* pArg)
11551180
if (doReal)
11561181
{
11571182
rc = REALFILE(pFile)->pMethods->xFileControl(REALFILE(pFile), op, pArg);
1183+
if (rc == SQLITE_OK && op == SQLITE_FCNTL_VFSNAME)
1184+
{
1185+
sqlite3mc_vfs* pVfsMC = p->pVfsMC;
1186+
char* zIn = *(char**)pArg;
1187+
char* zOut = sqlite3_mprintf("%s/%z", pVfsMC->base.zName, zIn);
1188+
*(char**)pArg = zOut;
1189+
if (zOut == 0) rc = SQLITE_NOMEM;
1190+
}
11581191
}
11591192
return rc;
11601193
}

0 commit comments

Comments
 (0)