1From ce201b3a6be487bb3eb48e1d102ba246332aba66 Mon Sep 17 00:00:00 2001 2From: MartinChoo <214582617@qq.com> 3Date: Wed, 23 Jul 2025 17:43:40 +0800 4Subject: [PATCH 08/12] Rekey multi process 5 6--- 7 src/sqlite3.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++-- 8 1 file changed, 90 insertions(+), 3 deletions(-) 9 10diff --git a/src/sqlite3.c b/src/sqlite3.c 11index 3f1195a..4c538a1 100644 12--- a/src/sqlite3.c 13+++ b/src/sqlite3.c 14@@ -15689,6 +15689,7 @@ typedef int VList; 15 #define RESERVED_BYTE (PENDING_BYTE+1) 16 #define SHARED_FIRST (PENDING_BYTE+2) 17 #define SHARED_SIZE 510 18+#define SHARED_CODEC_BYTE (PENDING_BYTE+2097) 19 20 /* 21 ** Wrapper around OS specific sqlite3_os_init() function. 22@@ -38682,6 +38683,10 @@ struct unixFile { 23 #endif 24 }; 25 26+#ifdef SQLITE_HAS_CODEC 27+static int CodecFileLock(Pager *pPager, short lockType); 28+#endif 29+ 30 /* This variable holds the process id (pid) from when the xRandomness() 31 ** method was called. If xOpen() is called from a different process id, 32 ** indicating that a fork() has occurred, the PRNG will be reset. 33@@ -39627,6 +39632,9 @@ struct unixInodeInfo { 34 sqlite3_mutex *pLockMutex; /* Hold this mutex for... */ 35 int nShared; /* Number of SHARED locks held */ 36 int nLock; /* Number of outstanding file locks */ 37+#if SQLITE_HAS_CODEC 38+ void *codecPager; 39+#endif 40 unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ 41 unsigned char bProcessLock; /* An exclusive process lock is held */ 42 UnixUnusedFd *pUnused; /* Unused file descriptors to close */ 43@@ -61697,6 +61705,9 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ 44 PAGERTRACE(("CLOSE %d\n", PAGERID(pPager))); 45 IOTRACE(("CLOSE %p\n", pPager)) 46 sqlite3OsClose(pPager->jfd); 47+#if SQLITE_OS_UNIX && defined(SQLITE_HAS_CODEC) 48+ if( pPager->xCodec ) CodecFileLock(pPager, F_UNLCK); 49+#endif 50 sqlite3OsClose(pPager->fd); 51 sqlite3PageFree(pTmp); 52 sqlite3PcacheClose(pPager->pPCache); 53@@ -255500,6 +255511,54 @@ void sqlite3CodecDetach(void *ctx){ 54 return; 55 } 56 57+#if SQLITE_OS_UNIX 58+static int CodecFileLock(Pager *pPager, short lockType) 59+{ 60+ sqlite3_file *fd = pPager->fd; 61+ unixFile *pFile = (unixFile *)fd; 62+ unixInodeInfo *pInode = pFile->pInode; 63+ if (pInode == NULL) { 64+ sqlite3_log(SQLITE_IOERR_RDLOCK, "Codec file lock %d go wrong", lockType); 65+ return SQLITE_IOERR_RDLOCK; 66+ } 67+ sqlite3_mutex_enter(pInode->pLockMutex); 68+ // last conntection release the lock 69+ if (lockType == F_UNLCK && pInode->nRef > 1) { 70+ sqlite3_mutex_leave(pInode->pLockMutex); 71+ return SQLITE_OK; 72+ } 73+ if (lockType == F_WRLCK && pInode->nRef > 1) { 74+ sqlite3_mutex_leave(pInode->pLockMutex); 75+ sqlite3_log(SQLITE_BUSY, "Codec file lock wrlock busy ref %d", pInode->nRef); 76+ return SQLITE_BUSY; 77+ } 78+ if (lockType == F_RDLCK && pInode->codecPager != 0 && pInode->codecPager != pPager) { 79+ sqlite3_mutex_leave(pInode->pLockMutex); 80+ sqlite3_log(SQLITE_BUSY, "Codec exists file lock wrlock"); 81+ return SQLITE_BUSY; 82+ } 83+ struct flock lock; 84+ lock.l_whence = SEEK_SET; 85+ lock.l_start = SHARED_CODEC_BYTE; 86+ lock.l_len = 1; 87+ // F_RDLCK, F_WRLCK, F_UNLCK 88+ lock.l_type = lockType; 89+ int rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); 90+ if (rc < 0) { 91+ int tErrno = errno; 92+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK); 93+ if (IS_LOCK_ERROR(rc)) { 94+ storeLastErrno(pFile, tErrno); 95+ } 96+ sqlite3_log(rc, "Codec file lock %d: errno = %d", lockType, tErrno); 97+ } else { 98+ pInode->codecPager = (lockType == F_WRLCK ? pPager : 0); 99+ } 100+ sqlite3_mutex_leave(pInode->pLockMutex); 101+ return rc; 102+} 103+#endif 104+ 105 int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ 106 if(db == NULL){ 107 return SQLITE_ERROR; 108@@ -255519,6 +255578,18 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ 109 return SQLITE_ERROR; 110 } 111 sqlite3_mutex_enter(db->mutex); 112+ Pager *pPager = p->pBt->pPager; 113+#if SQLITE_OS_UNIX 114+ if (pPager->fd != NULL && isOpen(pPager->fd)) { 115+ int ret = CodecFileLock(pPager, F_RDLCK); 116+ if(ret != SQLITE_OK){ 117+ sqlite3_free(ctx); 118+ sqlite3_mutex_leave(db->mutex); 119+ sqlite3_log(ret, "sqlite3CodecAttach: codec lock error"); 120+ return ret; 121+ } 122+ } 123+#endif 124 #ifdef SQLITE_CODEC_ATTACH_CHANGED 125 int rc = sqlite3CodecInitContext(ctx, p, pKey, nKey, nDb); 126 #else 127@@ -255526,6 +255597,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ 128 #endif /* SQLITE_CODEC_ATTACH_CHANGED */ 129 if(rc != SQLITE_OK){ 130 sqlite3_free(ctx); 131+ sqlite3_mutex_leave(db->mutex); 132 return rc; 133 } 134 sqlite3PagerSetCodec(sqlite3BtreePager(p), sqlite3Codec, NULL, sqlite3CodecDetach, (void *)ctx); 135@@ -255534,7 +255606,7 @@ int sqlite3CodecAttach(sqlite3* db, int nDb, const void *pKey, int nKey){ 136 p->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; 137 sqlite3BtreeSetPageSize(p, ctx->readCtx->codecConst.cipherPageSize, ctx->readCtx->codecConst.reserveSize, 0); 138 sqlite3BtreeSecureDelete(p, 1); 139- if(isOpen(p->pBt->pPager->fd)){ 140+ if(isOpen(pPager->fd)){ 141 sqlite3BtreeSetAutoVacuum(p, SQLITE_DEFAULT_AUTOVACUUM); 142 } 143 144@@ -255605,7 +255677,20 @@ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey){ 145 return rc; 146 } 147 sqlite3_mutex_enter(db->mutex); 148- (void)sqlite3BtreeBeginTrans(p, 1, 0); 149+ rc = sqlite3BtreeBeginTrans(p, 1, 0); 150+ if(rc != SQLITE_OK){ 151+ sqlite3_mutex_leave(db->mutex); 152+ sqlite3_log(rc, "sqlite3 rekey: error when begin trans %s.", sqlite3PagerFilename(pPager, 1)); 153+ return rc; 154+ } 155+#if SQLITE_OS_UNIX 156+ if((rc = CodecFileLock(pPager, F_WRLCK)) != SQLITE_OK){ 157+ (void)sqlite3BtreeRollback(p, SQLITE_ABORT_ROLLBACK, 0); 158+ sqlite3_mutex_leave(db->mutex); 159+ sqlite3_log(rc, "sqlite3_rekey_v2: error when lock %s.", sqlite3PagerFilename(pPager, 1)); 160+ return rc; 161+ } 162+#endif 163 sqlite3PagerPagecount(pPager, &pageCount); 164 // support hmac algo changed by using rekey operation 165 int oldHmacAlgo = ctx->writeCtx->codecConst.hmacAlgo; 166@@ -255640,8 +255725,10 @@ int sqlite3_rekey_v2(sqlite3 *db, const char *zDb, const void *pKey, int nKey){ 167 } 168 (void)sqlite3BtreeRollback(p, SQLITE_ABORT_ROLLBACK, 0); 169 } 170+#if SQLITE_OS_UNIX 171+ (void)CodecFileLock(pPager, F_RDLCK); 172+#endif 173 sqlite3_mutex_leave(db->mutex); 174- 175 return rc; 176 } 177 178-- 1792.47.0.windows.2 180 181