Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add connect/disconnect locking. And locking primitives for single-process mode. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f7fc6aeec8f3a568a472fa04b367b9ea |
User & Date: | dan 2013-10-23 20:28:42.954 |
Context
2013-10-23
| ||
22:43 | Fix undetected multiplication overflow check-in: 2eba06d522 user: peterreid tags: trunk | |
20:28 | Add connect/disconnect locking. And locking primitives for single-process mode. check-in: f7fc6aeec8 user: dan tags: trunk | |
19:31 | Progress on reading and writing frames from and to the log file. check-in: 5ba2ff0701 user: dan tags: trunk | |
Changes
Changes to src/btInt.h.
︙ | ︙ | |||
196 197 198 199 200 201 202 | /************************************************************************* ** Interface to bt_lock.c functionality. */ typedef struct BtShared BtShared; typedef struct BtLock BtLock; struct BtLock { /* These three are set by the bt_pager module and thereafter used by | | > > | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | /************************************************************************* ** Interface to bt_lock.c functionality. */ typedef struct BtShared BtShared; typedef struct BtLock BtLock; struct BtLock { /* These three are set by the bt_pager module and thereafter used by ** the bt_lock, bt_pager and bt_log modules. */ sqlite4_env *pEnv; /* SQLite environment */ bt_env *pVfs; /* Bt environment */ bt_file *pFd; /* Database file descriptor */ /* These are used only by the bt_lock module. */ BtShared *pShared; /* Shared by all handles on this file */ BtLock *pNext; /* Next connection using pShared */ u32 mExclLock; /* Mask of exclusive locks held */ u32 mSharedLock; /* Mask of shared locks held */ }; /* Connect and disconnect procedures */ int sqlite4BtLockConnect(BtLock*, int (*xRecover)(BtLock*)); int sqlite4BtLockDisconnect(BtLock*, int(*xCkpt)(BtLock*), int(*xDel)(BtLock*)); /* Obtain and release the WRITER lock */ |
︙ | ︙ |
Changes to src/bt_lock.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include "btInt.h" #include "sqliteInt.h" #include <string.h> #include <assert.h> #include <stdio.h> typedef struct BtFile BtFile; /* ** Global data. All global variables used by code in this file are grouped ** into the following structure instance. ** | > > > > > > > > > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include "btInt.h" #include "sqliteInt.h" #include <string.h> #include <assert.h> #include <stdio.h> #define BT_LOCK_DMS1 0 /* DMS1 */ #define BT_LOCK_DMS2_RW 1 /* DMS2/rw */ #define BT_LOCK_DMS2_RO 2 /* DMS2/ro */ #define BT_LOCK_WRITER 3 /* WRITER lock */ #define BT_LOCK_CKPTER 4 /* CHECKPOINTER lock */ #define BT_LOCK_READER0 5 /* Array of BT_NREADER locks */ #define BT_LOCK_UNLOCK 0 #define BT_LOCK_SHARED 1 #define BT_LOCK_EXCL 2 typedef struct BtFile BtFile; /* ** Global data. All global variables used by code in this file are grouped ** into the following structure instance. ** |
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 | /* ** Relinquish the mutex obtained by calling btLockMutexEnter(). */ static void btLockMutexLeave(){ /* todo... */ } /* ** Connect to the database as a read/write connection. If recovery ** is required (i.e. if this is the first connection to the db), invoke ** the xRecover() method. ** ** Return SQLITE4_OK if successful, or an SQLite4 error code if an | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | /* ** Relinquish the mutex obtained by calling btLockMutexEnter(). */ static void btLockMutexLeave(){ /* todo... */ } /* ** Attempt to obtain the lock identified by the iLock and bExcl parameters. ** If successful, return SQLITE4_OK. If the lock cannot be obtained because ** there exists some other conflicting lock, return SQLITE4_BUSY. If some ** other error occurs, return an SQLite4 error code. ** ** Parameter iLock must be one of BT_LOCK_WRITER, WORKER or CHECKPOINTER, ** or else a value returned by the BT_LOCK_READER macro. */ static int btLockLockop( BtLock *p, /* BtLock handle */ int iLock, /* Slot to lock */ int eOp, /* One of BT_LOCK_UNLOCK, SHARED or EXCL */ int bBlock /* True for a blocking lock */ ){ const u32 mask = ((u32)1 << iLock); int rc = SQLITE4_OK; BtShared *pShared = p->pShared; assert( iLock>=0 && iLock<(BT_LOCK_READER0 + BT_NREADER) ); assert( (BT_LOCK_READER0+BT_NREADER)<=32 ); assert( eOp==BT_LOCK_UNLOCK || eOp==BT_LOCK_SHARED || eOp==BT_LOCK_EXCL ); /* Check for a no-op. Proceed only if this is not one of those. */ if( (eOp==BT_LOCK_UNLOCK && (mask & (p->mExclLock|p->mSharedLock))!=0) || (eOp==BT_LOCK_SHARED && (mask & (p->mExclLock|p->mSharedLock))==0) || (eOp==BT_LOCK_EXCL && (mask & p->mExclLock)==0) ){ BtLock *pIter; int nExcl = 0; /* Number of connections holding EXCLUSIVE */ int nShared = 0; /* Number of connections holding SHARED */ sqlite4_mutex_enter(pShared->pClientMutex); /* Figure out the locks currently held by this process on iLock, not ** including any held by this connection. */ for(pIter=pShared->pLock; pIter; pIter=pIter->pNext){ assert( (pIter->mExclLock & pIter->mSharedLock)==pIter->mExclLock ); if( pIter!=p ){ assert( (pIter->mExclLock & p->mSharedLock)==0 ); assert( (pIter->mSharedLock & p->mExclLock)==0 ); if( mask & pIter->mExclLock ){ nExcl++; }else if( mask & pIter->mSharedLock ){ nShared++; } } } assert( nExcl==0 || nExcl==1 ); assert( nExcl==0 || nShared==0 ); switch( eOp ){ case BT_LOCK_UNLOCK: if( nShared==0 ){ #if 0 lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_UNLOCK); #endif } p->mExclLock &= ~mask; p->mSharedLock &= ~mask; break; case BT_LOCK_SHARED: if( nExcl ){ rc = SQLITE4_BUSY; }else{ if( nShared==0 ){ #if 0 rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED); #endif } if( rc==SQLITE4_OK ){ p->mSharedLock |= mask; p->mExclLock &= ~mask; } } break; default: assert( eOp==BT_LOCK_EXCL ); if( nExcl || nShared ){ rc = SQLITE4_BUSY; }else{ #if 0 rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL); #endif if( rc==SQLITE4_OK ){ p->mSharedLock |= mask; p->mExclLock |= mask; } } break; } sqlite4_mutex_leave(p->pClientMutex); } return rc; } /* ** Connect to the database as a read/write connection. If recovery ** is required (i.e. if this is the first connection to the db), invoke ** the xRecover() method. ** ** Return SQLITE4_OK if successful, or an SQLite4 error code if an |
︙ | ︙ | |||
131 132 133 134 135 136 137 | sqlite4_mutex_enter(pShared->pClientMutex); p->pNext = pShared->pLock; pShared->pLock = p; sqlite4_mutex_leave(pShared->pClientMutex); p->pShared = pShared; } | | > > > > > > > | > > > > > > > > | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | sqlite4_mutex_enter(pShared->pClientMutex); p->pNext = pShared->pLock; pShared->pLock = p; sqlite4_mutex_leave(pShared->pClientMutex); p->pShared = pShared; } if( rc==SQLITE4_OK ){ rc = btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_EXCL, 1); if( rc==SQLITE4_OK ){ rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_EXCL, 0); if( rc==SQLITE4_OK ){ rc = btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_EXCL, 0); } if( rc==SQLITE4_OK ){ rc = xRecover(p); } btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_UNLOCK, 0); btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_UNLOCK, 0); if( rc==SQLITE4_OK || rc==SQLITE4_BUSY ){ rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_SHARED, 0); } btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_UNLOCK, 0); } } return rc; } /* ** Disconnect the read/write connection passed as the first argument |
︙ | ︙ | |||
161 162 163 164 165 166 167 | BtLock *p, /* Locker handle */ int (*xCkpt)(BtLock*), /* Callback to checkpoint database */ int (*xDel)(BtLock*) /* Callback to delete wal+shm files */ ){ BtShared *pShared = p->pShared; BtLock **pp; int rc; /* Return code */ | < < < < > > > > > > > > > > > > > > > > > > | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | BtLock *p, /* Locker handle */ int (*xCkpt)(BtLock*), /* Callback to checkpoint database */ int (*xDel)(BtLock*) /* Callback to delete wal+shm files */ ){ BtShared *pShared = p->pShared; BtLock **pp; int rc; /* Return code */ sqlite4_mutex_enter(pShared->pClientMutex); for(pp=&p->pShared->pLock; *pp!=p; pp=&(*pp)->pNext); *pp = (*pp)->pNext; sqlite4_mutex_leave(pShared->pClientMutex); rc = btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_EXCL, 1); if( rc==SQLITE4_OK ){ rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_EXCL, 0); if( rc==SQLITE4_OK ){ rc = xCkpt(p); } if( rc==SQLITE4_OK ){ rc = btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_EXCL, 0); } if( rc==SQLITE4_OK ){ rc = xDel(p); } if( rc==SQLITE4_BUSY ) rc = SQLITE4_OK; btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_UNLOCK, 0); btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_UNLOCK, 0); btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_UNLOCK, 0); } btLockMutexEnter(); pShared->nRef--; if( pShared->nRef==0 ){ int i; BtShared **ppS; for(ppS=&gShared.pDatabase; *ppS!=pShared; ppS=&(*ppS)->pNext); |
︙ | ︙ |
Changes to src/bt_log.c.
︙ | ︙ | |||
236 237 238 239 240 241 242 243 244 245 246 247 248 249 | } static void btLogZeroSnapshot(BtLog *pLog){ bt_env *pVfs = pLog->pLock->pVfs; memset(&pLog->snapshot, 0, sizeof(BtShmHdr)); pLog->snapshot.nSector = pVfs->xSectorSize(pLog->pFd); } /* ** Open the log file for pager pPager. If successful, return the BtLog* ** handle via output variable *ppLog. If parameter bRecover is true, then ** also run database recovery before returning. In this case, the caller ** has already obtained the required locks. */ | > > > > > > > > | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | } static void btLogZeroSnapshot(BtLog *pLog){ bt_env *pVfs = pLog->pLock->pVfs; memset(&pLog->snapshot, 0, sizeof(BtShmHdr)); pLog->snapshot.nSector = pVfs->xSectorSize(pLog->pFd); } /* ** Run log recovery. In other words, read the log file from disk and ** initialize the shared-memory accordingly. */ static int btLogRecover(BtLog *pLog){ return SQLITE4_OK; } /* ** Open the log file for pager pPager. If successful, return the BtLog* ** handle via output variable *ppLog. If parameter bRecover is true, then ** also run database recovery before returning. In this case, the caller ** has already obtained the required locks. */ |
︙ | ︙ | |||
263 264 265 266 267 268 269 | memset(pLog, 0, sizeof(BtLog)); pLog->pLock = (BtLock*)pPager; zWal = sqlite4BtPagerFilename(pPager, BT_PAGERFILE_LOG); rc = pVfs->xOpen(pEnv, pVfs, zWal, 0, &pLog->pFd); if( rc==SQLITE4_OK && bRecover ){ | < < > > > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | memset(pLog, 0, sizeof(BtLog)); pLog->pLock = (BtLock*)pPager; zWal = sqlite4BtPagerFilename(pPager, BT_PAGERFILE_LOG); rc = pVfs->xOpen(pEnv, pVfs, zWal, 0, &pLog->pFd); if( rc==SQLITE4_OK && bRecover ){ rc = btLogMapShm(pLog, 0); if( rc==SQLITE4_OK ){ btLogZeroSnapshot(pLog); rc = btLogRecover(pLog); } if( rc==SQLITE4_OK ){ rc = btLogUpdateSharedHdr(pLog); } } open_out: if( rc!=SQLITE4_OK ){ sqlite4_free(pEnv, pLog); |
︙ | ︙ |