• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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