Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Clean up the locking in the btree logic. (CVS 4316) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
967ab229af462a8ae663090ea36b4cc1 |
User & Date: | drh 2007-08-28 22:24:35.000 |
Context
2007-08-28
| ||
23:28 | The shared_err test runs with no errors. But a potential deadlock has been discovered and is still unfixed. (CVS 4317) (check-in: f84550be0a user: drh tags: trunk) | |
22:24 | Clean up the locking in the btree logic. (CVS 4316) (check-in: 967ab229af user: drh tags: trunk) | |
20:36 | Fix memory leak of InteriorReader.term. Comes up when doing queries against large segments. (CVS 4315) (check-in: 6c617bd89f user: shess tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.414 2007/08/28 22:24:35 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" |
︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 | ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or ** SQLITE_LOCKED if not. */ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pIter; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } | > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | ** SQLITE_OK if the lock may be obtained (by calling lockTable()), or ** SQLITE_LOCKED if not. */ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pIter; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } |
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 | ** SQLITE_NOMEM may also be returned. */ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } | > | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | ** SQLITE_NOMEM may also be returned. */ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pLock = 0; BtLock *pIter; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ return SQLITE_OK; } |
︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 | /* ** Release all the table locks (locks obtained via calls to the lockTable() ** procedure) held by Btree handle p. */ static void unlockAllTables(Btree *p){ BtLock **ppIter = &p->pBt->pLock; assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( p->sharable || 0==*ppIter ); while( *ppIter ){ BtLock *pLock = *ppIter; if( pLock->pBtree==p ){ *ppIter = pLock->pNext; | > | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | /* ** Release all the table locks (locks obtained via calls to the lockTable() ** procedure) held by Btree handle p. */ static void unlockAllTables(Btree *p){ BtLock **ppIter = &p->pBt->pLock; assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( p->sharable || 0==*ppIter ); while( *ppIter ){ BtLock *pLock = *ppIter; if( pLock->pBtree==p ){ *ppIter = pLock->pNext; |
︙ | ︙ | |||
232 233 234 235 236 237 238 239 240 241 242 243 244 245 | static void releasePage(MemPage *pPage); /* Forward reference */ #ifndef SQLITE_OMIT_INCRBLOB /* ** Invalidate the overflow page-list cache for cursor pCur, if any. */ static void invalidateOverflowCache(BtCursor *pCur){ sqlite3_free(pCur->aOverflow); pCur->aOverflow = 0; } /* ** Invalidate the overflow page-list cache for all cursors opened ** on the shared btree structure pBt. | > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | static void releasePage(MemPage *pPage); /* Forward reference */ #ifndef SQLITE_OMIT_INCRBLOB /* ** Invalidate the overflow page-list cache for cursor pCur, if any. */ static void invalidateOverflowCache(BtCursor *pCur){ assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); sqlite3_free(pCur->aOverflow); pCur->aOverflow = 0; } /* ** Invalidate the overflow page-list cache for all cursors opened ** on the shared btree structure pBt. |
︙ | ︙ | |||
261 262 263 264 265 266 267 | ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. */ static int saveCursorPosition(BtCursor *pCur){ int rc; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); | | | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. */ static int saveCursorPosition(BtCursor *pCur){ int rc; assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); /* If this is an intKey table, then the above call to BtreeKeySize() ** stores the integer key in pCur->nKey. In this case this value is ** all that is required. Otherwise, if pCur is not open on an intKey ** table, then malloc space for and store the pCur->nKey bytes of key |
︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | ** Save the positions of all cursors except pExcept open on the table ** with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } } } return SQLITE_OK; } /* ** Clear the current cursor position. */ static void clearCursorPosition(BtCursor *pCur){ | > | > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | ** Save the positions of all cursors except pExcept open on the table ** with root-page iRoot. Usually, this is called just before cursor ** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && p->eState==CURSOR_VALID ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; } } } return SQLITE_OK; } /* ** Clear the current cursor position. */ static void clearCursorPosition(BtCursor *pCur){ assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); sqlite3_free(pCur->pKey); pCur->pKey = 0; pCur->eState = CURSOR_INVALID; } /* ** Restore the cursor to the position it was in (or as close to as possible) ** when saveCursorPosition() was called. Note that this call deletes the ** saved position info stored by saveCursorPosition(), so there can be ** at most one effective restoreOrClearCursorPosition() call after each ** saveCursorPosition(). ** ** If the second argument argument - doSeek - is false, then instead of ** returning the cursor to it's saved position, any saved position is deleted ** and the cursor state set to CURSOR_INVALID. */ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_REQUIRESEEK ); #ifndef SQLITE_OMIT_INCRBLOB if( pCur->isIncrblobHandle ){ return SQLITE_ABORT; } #endif pCur->eState = CURSOR_INVALID; |
︙ | ︙ | |||
1048 1049 1050 1051 1052 1053 1054 1055 1056 | ** reaches zero. We need to unref the pParent pointer when that ** happens. */ static void pageDestructor(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; | > | > | 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | ** reaches zero. We need to unref the pParent pointer when that ** happens. */ static void pageDestructor(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); assert( pPage->isInit==0 || sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; assert( pPage->isInit==1 ); assert( pParent->pBt==pPage->pBt ); pPage->pParent = 0; releasePage(pParent); } pPage->isInit = 0; } /* |
︙ | ︙ | |||
1111 1112 1113 1114 1115 1116 1117 | #ifdef SQLITE_OMIT_MEMORYDB const int isMemdb = 0; #else const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); #endif #endif | | | < < | < | | | > | 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 | #ifdef SQLITE_OMIT_MEMORYDB const int isMemdb = 0; #else const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); #endif #endif assert( pSqlite!=0 ); assert( sqlite3_mutex_held(pSqlite->mutex) ); pVfs = pSqlite->pVfs; p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; } p->inTrans = TRANS_NONE; p->pSqlite = pSqlite; #if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) /* ** If this Btree is a candidate for shared cache, try to find an ** existing BtShared object that we can share with */ if( (flags & BTREE_PRIVATE)==0 && isMemdb==0 && (pSqlite->flags & SQLITE_Vtab)==0 && zFilename && zFilename[0] && sqlite3SharedCacheEnabled ){ char *zFullPathname = (char *)sqlite3_malloc(pVfs->mxPathname); sqlite3_mutex *mutexShared; p->sharable = 1; if( pSqlite ){ pSqlite->flags |= SQLITE_SharedCache; } if( !zFullPathname ){ sqlite3_free(p); return SQLITE_NOMEM; } sqlite3OsFullPathname(pVfs, zFilename, zFullPathname); mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(mutexShared); for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) && sqlite3PagerVfs(pBt->pPager)==pVfs ){ p->pBt = pBt; pBt->nRef++; break; } } sqlite3_mutex_leave(mutexShared); sqlite3_free(zFullPathname); |
︙ | ︙ | |||
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 | ** Close an open database and invalidate all cursors. */ int sqlite3BtreeClose(Btree *p){ BtShared *pBt = p->pBt; BtCursor *pCur; /* Close all cursors opened via this handle. */ sqlite3BtreeEnter(p); pCur = pBt->pCursor; while( pCur ){ BtCursor *pTmp = pCur; pCur = pCur->pNext; if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); | > | 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 | ** Close an open database and invalidate all cursors. */ int sqlite3BtreeClose(Btree *p){ BtShared *pBt = p->pBt; BtCursor *pCur; /* Close all cursors opened via this handle. */ assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); pCur = pBt->pCursor; while( pCur ){ BtCursor *pTmp = pCur; pCur = pCur->pNext; if( pTmp->pBtree==p ){ sqlite3BtreeCloseCursor(pTmp); |
︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 | return SQLITE_OK; } #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) /* ** Short-cuts for entering and leaving mutexes on a cursor. */ | > | < < < < < > | 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | return SQLITE_OK; } #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) /* ** Short-cuts for entering and leaving mutexes on a cursor. */ # define cursorEnter(X) assert( sqlite3_mutex_held(X->pBt->mutex) ) # define cursorLeave(X) #else # define cursorEnter(X) # define cursorLeave(X) #endif /* !SQLITE_OMIT_SHARED_CACHE */ /* ** Change the busy handler callback function. */ int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ BtShared *pBt = p->pBt; assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); pBt->pBusyHandler = pHandler; sqlite3PagerSetBusyhandler(pBt->pPager, pHandler); sqlite3BtreeLeave(p); return SQLITE_OK; } |
︙ | ︙ | |||
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 | ** an abrupt power failure when synchronous is off, the database ** could be left in an inconsistent and unrecoverable state. ** Synchronous is on by default so database corruption is not ** normally a worry. */ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); sqlite3PagerSetCachesize(pBt->pPager, mxPage); sqlite3BtreeLeave(p); return SQLITE_OK; } /* ** Change the way data is synced to disk in order to increase or decrease ** how well the database resists damage due to OS crashes and power ** failures. Level 1 is the same as asynchronous (no syncs() occur and ** there is a high probability of damage) Level 2 is the default. There ** is a very low but non-zero probability of damage. Level 3 reduces the ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); sqlite3BtreeLeave(p); return SQLITE_OK; } #endif /* ** Return TRUE if the given btree is set to safety level 1. In other ** words, return TRUE if no sync() occurs on the disk files. */ int sqlite3BtreeSyncDisabled(Btree *p){ BtShared *pBt = p->pBt; int rc; | > > | > | 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 | ** an abrupt power failure when synchronous is off, the database ** could be left in an inconsistent and unrecoverable state. ** Synchronous is on by default so database corruption is not ** normally a worry. */ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetCachesize(pBt->pPager, mxPage); sqlite3BtreeLeave(p); return SQLITE_OK; } /* ** Change the way data is synced to disk in order to increase or decrease ** how well the database resists damage due to OS crashes and power ** failures. Level 1 is the same as asynchronous (no syncs() occur and ** there is a high probability of damage) Level 2 is the default. There ** is a very low but non-zero probability of damage. Level 3 reduces the ** probability of damage to near zero but with a write performance reduction. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); sqlite3BtreeLeave(p); return SQLITE_OK; } #endif /* ** Return TRUE if the given btree is set to safety level 1. In other ** words, return TRUE if no sync() occurs on the disk files. */ int sqlite3BtreeSyncDisabled(Btree *p){ BtShared *pBt = p->pBt; int rc; assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); assert( pBt && pBt->pPager ); rc = sqlite3PagerNosync(pBt->pPager); sqlite3BtreeLeave(p); return rc; } #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) /* |
︙ | ︙ | |||
1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 | Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* Move page iDbPage from it's current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); if( rc!=SQLITE_OK ){ return rc; | > | 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 | Pgno iDbPage = pDbPage->pgno; Pager *pPager = pBt->pPager; int rc; assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pDbPage->pBt==pBt ); /* Move page iDbPage from it's current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); if( rc!=SQLITE_OK ){ return rc; |
︙ | ︙ | |||
2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 | BtCursor **ppCur /* Write new cursor here */ ){ int rc; BtCursor *pCur; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } if( checkReadLocks(p, iTable, 0) ){ return SQLITE_LOCKED; | > | 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 | BtCursor **ppCur /* Write new cursor here */ ){ int rc; BtCursor *pCur; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; } if( checkReadLocks(p, iTable, 0) ){ return SQLITE_LOCKED; |
︙ | ︙ | |||
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 | /* Now that no other errors can occur, finish filling in the BtCursor ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; pCur->wrFlag = wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; | > | 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 | /* Now that no other errors can occur, finish filling in the BtCursor ** variables, link the cursor into the BtShared list and set *ppCur (the ** output argument to this function). */ pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; pCur->pBt = pBt; pCur->wrFlag = wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; |
︙ | ︙ | |||
2672 2673 2674 2675 2676 2677 2678 | /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ | | | > < > < < > < | > < > | 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 | /* ** Close a cursor. The read lock on the database file is released ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBt; assert( sqlite3_mutex_held(pCur->pBt->mutex) ); assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); clearCursorPosition(pCur); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ pBt->pCursor = pCur->pNext; } if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; } releasePage(pCur->pPage); unlockBtreeIfUnused(pBt); invalidateOverflowCache(pCur); sqlite3_free(pCur); return SQLITE_OK; } /* ** Make a temporary cursor by filling in the fields of pTempCur. ** The temporary cursor is not on the cursor list for the Btree. */ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ cursorEnter(pCur); memcpy(pTempCur, pCur, sizeof(*pCur)); pTempCur->pNext = 0; pTempCur->pPrev = 0; if( pTempCur->pPage ){ sqlite3PagerRef(pTempCur->pPage->pDbPage); } cursorLeave(pCur); } /* ** Delete a temporary cursor such as was made by the CreateTemporaryCursor() ** function above. */ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ cursorEnter(pCur); if( pCur->pPage ){ sqlite3PagerUnref(pCur->pPage->pDbPage); } cursorLeave(pCur); } /* ** Make sure the BtCursor* given in the argument has a valid ** BtCursor.info structure. If it is not already valid, call ** sqlite3BtreeParseCell() to fill it in. ** |
︙ | ︙ | |||
2774 2775 2776 2777 2778 2779 2780 | ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc; | | < | < | 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 | ** ** For a table with the INTKEY flag set, this routine returns the key ** itself, not the number of bytes in the key. */ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc; assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nKey; } } return rc; } /* ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int rc; assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); if( pCur->eState==CURSOR_INVALID ){ /* Not pointing at a valid entry - set *pSize to 0. */ *pSize = 0; }else{ getCellInfo(pCur); *pSize = pCur->info.nData; } } return rc; } /* ** Given the page number of an overflow page in the database (parameter ** ovfl), this function finds the page number of the next page in the ** linked list of overflow pages. If possible, it uses the auto-vacuum |
︙ | ︙ | |||
2974 2975 2976 2977 2978 2979 2980 | int skipKey, /* offset begins at data if this is true */ int eOp /* zero to read. non-zero to write. */ ){ unsigned char *aPayload; int rc = SQLITE_OK; u32 nKey; int iIdx = 0; | | | | | 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 | int skipKey, /* offset begins at data if this is true */ int eOp /* zero to read. non-zero to write. */ ){ unsigned char *aPayload; int rc = SQLITE_OK; u32 nKey; int iIdx = 0; MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; nKey = (pPage->intKey ? 0 : pCur->info.nKey); if( skipKey ){ offset += nKey; |
︙ | ︙ | |||
3107 3108 3109 3110 3111 3112 3113 | ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; | | | | | | | 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 | ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; cursorEnter(pCur); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ cursorLeave(pCur); return SQLITE_CORRUPT_BKPT; } assert( pCur->pPage->intKey==0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); } cursorLeave(pCur); return rc; } /* ** Read part of the data associated with cursor pCur. Exactly ** "amt" bytes will be transfered into pBuf[]. The transfer ** begins at "offset". ** ** Return SQLITE_OK on success or an error code if anything goes ** wrong. An error is returned if "offset+amt" is larger than ** the available payload. */ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; cursorEnter(pCur); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); } cursorLeave(pCur); return rc; } /* ** Return a pointer to payload information from the entry that the ** pCur cursor is pointing to. The pointer is to the beginning of ** the key if skipKey==0 and it points to the beginning of data if |
︙ | ︙ | |||
3179 3180 3181 3182 3183 3184 3185 | unsigned char *aPayload; MemPage *pPage; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); | | | 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 | unsigned char *aPayload; MemPage *pPage; u32 nKey; int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; if( pPage->intKey ){ nKey = 0; |
︙ | ︙ | |||
3219 3220 3221 3222 3223 3224 3225 | ** Hence, a mutex on the BtShared should be held prior to calling ** this routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ | | | | | 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 | ** Hence, a mutex on the BtShared should be held prior to calling ** this routine. ** ** These routines is used to get quick access to key and data ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 0); } return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 1); } return 0; } /* ** Move the cursor down to a new child page. The newPgno argument is the ** page number of the child page to move to. */ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; BtShared *pBt = pCur->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; pNewPage->idxParent = pCur->idx; pOldPage = pCur->pPage; |
︙ | ︙ | |||
3294 3295 3296 3297 3298 3299 3300 | ** the largest cell index. */ void sqlite3BtreeMoveToParent(BtCursor *pCur){ MemPage *pParent; MemPage *pPage; int idxParent; | | | < | 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 | ** the largest cell index. */ void sqlite3BtreeMoveToParent(BtCursor *pCur){ MemPage *pParent; MemPage *pPage; int idxParent; cursorEnter(pCur); assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pPage!=0 ); assert( !sqlite3BtreeIsRootPage(pPage) ); pParent = pPage->pParent; assert( pParent!=0 ); idxParent = pPage->idxParent; sqlite3PagerRef(pParent->pDbPage); releasePage(pPage); pCur->pPage = pParent; pCur->info.nSize = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; cursorLeave(pCur); } /* ** Move the cursor to the root page */ static int moveToRoot(BtCursor *pCur){ MemPage *pRoot; int rc = SQLITE_OK; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pCur->eState==CURSOR_REQUIRESEEK ){ clearCursorPosition(pCur); } pRoot = pCur->pPage; if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ assert( pRoot->isInit ); |
︙ | ︙ | |||
3364 3365 3366 3367 3368 3369 3370 | ** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; | | < | 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 | ** in ascending order. */ static int moveToLeftmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); pgno = get4byte(findCell(pPage, pCur->idx)); rc = moveToChild(pCur, pgno); } return rc; |
︙ | ︙ | |||
3390 3391 3392 3393 3394 3395 3396 | ** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; | | < | | 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 | ** key in ascending order. */ static int moveToRightmost(BtCursor *pCur){ Pgno pgno; int rc = SQLITE_OK; MemPage *pPage; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pCur->idx = pPage->nCell; rc = moveToChild(pCur, pgno); } if( rc==SQLITE_OK ){ pCur->idx = pPage->nCell - 1; pCur->info.nSize = 0; } return SQLITE_OK; } /* Move the cursor to the first entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; rc = SQLITE_OK; |
︙ | ︙ | |||
3436 3437 3438 3439 3440 3441 3442 | /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; | | | 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 | /* Move the cursor to the last entry in the table. Return SQLITE_OK ** on success. Set *pRes to 0 if the cursor actually points to something ** or set *pRes to 1 if the table is empty. */ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ assert( pCur->pPage->nCell==0 ); *pRes = 1; }else{ |
︙ | ︙ | |||
3489 3490 3491 3492 3493 3494 3495 | const void *pKey, /* The key content for indices. Not used by tables */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; | | | 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 | const void *pKey, /* The key content for indices. Not used by tables */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc ){ return rc; } assert( pCur->pPage ); assert( pCur->pPage->isInit ); |
︙ | ︙ | |||
3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 | return (CURSOR_VALID!=pCur->eState); } /* ** Return the database connection handle for a cursor. */ sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ return pCur->pBtree->pSqlite; } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ static int btreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } assert( pRes!=0 ); pPage = pCur->pPage; if( CURSOR_INVALID==pCur->eState ){ | > > | 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 | return (CURSOR_VALID!=pCur->eState); } /* ** Return the database connection handle for a cursor. */ sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); return pCur->pBtree->pSqlite; } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ static int btreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } assert( pRes!=0 ); pPage = pCur->pPage; if( CURSOR_INVALID==pCur->eState ){ |
︙ | ︙ | |||
3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 | ** this routine was called, then set *pRes=1. */ static int btreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; | > | 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 | ** this routine was called, then set *pRes=1. */ static int btreePrevious(BtCursor *pCur, int *pRes){ int rc; Pgno pgno; MemPage *pPage; assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; } if( CURSOR_INVALID==pCur->eState ){ *pRes = 1; return SQLITE_OK; |
︙ | ︙ | |||
5482 5483 5484 5485 5486 5487 5488 | int szNew; MemPage *pPage; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; unsigned char *oldCell; unsigned char *newCell = 0; | | | | | | | 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 | int szNew; MemPage *pPage; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; unsigned char *oldCell; unsigned char *newCell = 0; cursorEnter(pCur); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( !pCur->wrFlag ){ cursorLeave(pCur); return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Save the positions of any other cursors open on this table */ clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ cursorLeave(pCur); return rc; } pPage = pCur->pPage; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->leafData ); TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", |
︙ | ︙ | |||
5554 5555 5556 5557 5558 5559 5560 | /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ /* fflush(stdout); */ if( rc==SQLITE_OK ){ moveToRoot(pCur); } end_insert: sqlite3_free(newCell); | | | | | | | | | | 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 | /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ /* fflush(stdout); */ if( rc==SQLITE_OK ){ moveToRoot(pCur); } end_insert: sqlite3_free(newCell); cursorLeave(pCur); return rc; } /* ** Delete the entry that the cursor is pointing to. The cursor ** is left pointing at a random location. */ int sqlite3BtreeDelete(BtCursor *pCur){ MemPage *pPage = pCur->pPage; unsigned char *pCell; int rc; Pgno pgnoChild = 0; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; cursorEnter(pCur); assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ cursorLeave(pCur); return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ cursorLeave(pCur); return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } /* Restore the current cursor position (a no-op if the cursor is not in ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors ** open on the same table. Then call sqlite3PagerWrite() on the page ** that the entry will be deleted from. */ if( (rc = restoreOrClearCursorPosition(pCur))!=0 || (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 ){ cursorLeave(pCur); return rc; } /* Locate the cell within it's page and leave pCell pointing to the ** data. The clearCell() call frees any overflow pages associated with the ** cell. The cell itself is still intact. */ pCell = findCell(pPage, pCur->idx); if( !pPage->leaf ){ pgnoChild = get4byte(pCell); } rc = clearCell(pPage, pCell); if( rc ){ cursorLeave(pCur); return rc; } if( !pPage->leaf ){ /* ** The entry we are about to delete is not a leaf so if we do not ** do something we will leave a hole on an internal page. |
︙ | ︙ | |||
5675 5676 5677 5678 5679 5680 5681 | pCur->pgnoRoot, pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); rc = balance(pPage, 0); } if( rc==SQLITE_OK ){ moveToRoot(pCur); } | | > > | 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 | pCur->pgnoRoot, pPage->pgno)); dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); rc = balance(pPage, 0); } if( rc==SQLITE_OK ){ moveToRoot(pCur); } cursorLeave(pCur); return rc; } /* ** Create a new BTree table. Write into *piTable the page ** number for the root page of the new table. ** ** The type of type is determined by the flags parameter. Only the ** following values of flags are currently in use. Other values for ** flags might not work: ** ** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys ** BTREE_ZERODATA Used for SQL indices */ static int btreeCreateTable(Btree *p, int *piTable, int flags){ BtShared *pBt = p->pBt; MemPage *pRoot; Pgno pgnoRoot; int rc; assert( sqlite3_mutex_held(p->pSqlite->mutex) ); assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction first */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; return rc; } assert( !pBt->readOnly ); |
︙ | ︙ | |||
6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 | */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; } /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ Pager *sqlite3BtreePager(Btree *p){ | > < < | 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 | */ int sqlite3BtreeFlags(BtCursor *pCur){ /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); assert( pPage->pBt==pCur->pBt ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; } /* ** Return the pager associated with a BTree. This routine is used for ** testing and debugging only. */ Pager *sqlite3BtreePager(Btree *p){ return p->pBt->pPager; } #ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Append a message to the error message string. */ |
︙ | ︙ | |||
6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 | *pnErr = sCheck.nErr; return sCheck.zErrMsg; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); return sqlite3PagerFilename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); return sqlite3PagerDirname(p->pBt->pPager); } /* ** Return the pathname of the journal file for this database. The return ** value of this routine is the same regardless of whether the journal file ** has been created or not. */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); return sqlite3PagerJournalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. | > > > > > > > > > > > > | 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 | *pnErr = sCheck.nErr; return sCheck.zErrMsg; } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. ** ** The pager filename is invariant as long as the pager is ** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerFilename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. ** ** The pager directory name is invariant as long as the pager is ** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerDirname(p->pBt->pPager); } /* ** Return the pathname of the journal file for this database. The return ** value of this routine is the same regardless of whether the journal file ** has been created or not. ** ** The pager journal filename is invariant as long as the pager is ** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerJournalname(p->pBt->pPager); } #ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. |
︙ | ︙ | |||
6681 6682 6683 6684 6685 6686 6687 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ | | | 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ assert( p==0 || sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ int sqlite3BtreeIsInStmt(Btree *p){ |
︙ | ︙ | |||
6720 6721 6722 6723 6724 6725 6726 | ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the ** blob of allocated memory. This function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; | < | 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 | ** Just before the shared-btree is closed, the function passed as the ** xFree argument when the memory allocation was made is invoked on the ** blob of allocated memory. This function should not call sqlite3_free() ** on the memory, the btree layer does that. */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); if( !pBt->pSchema ){ pBt->pSchema = sqlite3MallocZero(nBytes); pBt->xFreeSchema = xFree; } sqlite3BtreeLeave(p); return pBt->pSchema; |
︙ | ︙ | |||
6772 6773 6774 6775 6776 6777 6778 | ** Argument pCsr must be a cursor opened for writing on an ** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ | | | | | 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 | ** Argument pCsr must be a cursor opened for writing on an ** INTKEY table currently pointing at a valid table entry. ** This function modifies the data stored as part of that entry. ** Only the data content may only be modified, it is not possible ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ assert( sqlite3BtreeMutexHeld(pCsr->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); if( pCsr->eState==CURSOR_REQUIRESEEK ){ return SQLITE_ABORT; } /* Check some preconditions: ** (a) the cursor is open for writing, ** (b) there is no read-lock on the table being modified and ** (c) the cursor points at a valid row of an intKey table. */ if( !pCsr->wrFlag ){ return SQLITE_READONLY; } assert( !pCsr->pBt->readOnly && pCsr->pBt->inTransaction==TRANS_WRITE ); if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } if( pCsr->eState==CURSOR_INVALID || !pCsr->pPage->intKey ){ return SQLITE_ERROR; } |
︙ | ︙ | |||
6810 6811 6812 6813 6814 6815 6816 | ** ** This function sets a flag only. The actual page location cache ** (stored in BtCursor.aOverflow[]) is allocated and used by function ** accessPayload() (the worker function for sqlite3BtreeData() and ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ | | | 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 | ** ** This function sets a flag only. The actual page location cache ** (stored in BtCursor.aOverflow[]) is allocated and used by function ** accessPayload() (the worker function for sqlite3BtreeData() and ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); assert(!pCur->isIncrblobHandle); assert(!pCur->aOverflow); pCur->isIncrblobHandle = 1; } #endif |
Changes to src/btreeInt.h.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btreeInt.h,v 1.11 2007/08/28 22:24:35 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
314 315 316 317 318 319 320 | ** For some database files, the same underlying database cache might be ** shared between multiple connections. In that case, each contection ** has it own pointer to this object. But each instance of this object ** points to the same BtShared object. The database cache and the ** schema associated with the database file are all contained within ** the BtShared object. ** | | > > > > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | ** For some database files, the same underlying database cache might be ** shared between multiple connections. In that case, each contection ** has it own pointer to this object. But each instance of this object ** points to the same BtShared object. The database cache and the ** schema associated with the database file are all contained within ** the BtShared object. ** ** All fields in this structure are accessed under sqlite3.mutex. ** The pBt pointer itself may not be changed while there exists cursors ** in the referenced BtShared that point back to this Btree since those ** cursors have to do go through this Btree to find their BtShared and ** they often do so without holding sqlite3.mutex. */ struct Btree { sqlite3 *pSqlite; /* The database connection holding this btree */ BtShared *pBt; /* Sharable content of this btree */ u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ u8 sharable; /* True if we can share pBt with other pSqlite */ u8 locked; /* True if pSqlite currently has pBt locked */ |
︙ | ︙ | |||
415 416 417 418 419 420 421 | ** MemPage.aCell[] of the entry. ** ** When a single database file can shared by two more database connections, ** but cursors cannot be shared. Each cursor is associated with a ** particular database connection identified BtCursor.pBtree.pSqlite. ** ** Fields in this structure are accessed under the BtShared.mutex | | < > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | ** MemPage.aCell[] of the entry. ** ** When a single database file can shared by two more database connections, ** but cursors cannot be shared. Each cursor is associated with a ** particular database connection identified BtCursor.pBtree.pSqlite. ** ** Fields in this structure are accessed under the BtShared.mutex ** found at self->pBt->mutex. */ struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ void *pArg; /* First arg to xCompare() */ Pgno pgnoRoot; /* The root page of this tree */ MemPage *pPage; /* Page that contains the entry */ int idx; /* Index of the entry in pPage->aCell[] */ CellInfo info; /* A parse of the cell we are pointing at */ |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.440 2007/08/28 22:24:35 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
160 161 162 163 164 165 166 | */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; | | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | */ if( pParse->cookieGoto>0 ){ u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb, db->aDb[iDb].pBt); sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } #ifndef SQLITE_OMIT_VIRTUALTABLE if( pParse->pVirtualLock ){ char *vtab = (char *)pParse->pVirtualLock->pVtab; sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB); |
︙ | ︙ |
Changes to src/mutex_unix.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2007 August 28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2007 August 28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** ** $Id: mutex_unix.c,v 1.2 2007/08/28 22:24:35 drh Exp $ */ #include "sqliteInt.h" /* ** The code in this file is only used if we are compiling threadsafe ** under unix with pthreads. ** |
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** Each recursive mutex is an instance of the following structure. */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ int nRef; /* Number of entrances */ pthread_t owner; /* Thread that is within this mutex */ }; /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite ** will unwind its stack and return an error. The argument | > > > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** Each recursive mutex is an instance of the following structure. */ struct sqlite3_mutex { pthread_mutex_t mutex; /* Mutex controlling the lock */ int id; /* Mutex type */ int nRef; /* Number of entrances */ pthread_t owner; /* Thread that is within this mutex */ #ifdef SQLITE_DEBUG int trace; /* True to trace changes */ #endif }; /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. SQLite ** will unwind its stack and return an error. The argument |
︙ | ︙ | |||
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 | */ void sqlite3_mutex_enter(sqlite3_mutex *p){ assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); pthread_mutex_lock(&p->mutex); p->owner = pthread_self(); p->nRef++; } int sqlite3_mutex_try(sqlite3_mutex *p){ int rc; assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); if( pthread_mutex_trylock(&p->mutex)==0 ){ p->owner = pthread_self(); p->nRef++; rc = SQLITE_OK; }else{ rc = SQLITE_BUSY; } return rc; } /* ** The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ void sqlite3_mutex_leave(sqlite3_mutex *p){ assert( p ); assert( sqlite3_mutex_held(p) ); p->nRef--; assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); pthread_mutex_unlock(&p->mutex); } /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use only inside assert() statements. On some platforms, ** there might be race conditions that can cause these routines to | > > > > > > > > > > > > > > > | 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 194 195 196 197 198 199 200 201 202 | */ void sqlite3_mutex_enter(sqlite3_mutex *p){ assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); pthread_mutex_lock(&p->mutex); p->owner = pthread_self(); p->nRef++; #ifdef SQLITE_DEBUG if( p->trace ){ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif } int sqlite3_mutex_try(sqlite3_mutex *p){ int rc; assert( p ); assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); if( pthread_mutex_trylock(&p->mutex)==0 ){ p->owner = pthread_self(); p->nRef++; rc = SQLITE_OK; #ifdef SQLITE_DEBUG if( p->trace ){ printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif }else{ rc = SQLITE_BUSY; } return rc; } /* ** The sqlite3_mutex_leave() routine exits a mutex that was ** previously entered by the same thread. The behavior ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ void sqlite3_mutex_leave(sqlite3_mutex *p){ assert( p ); assert( sqlite3_mutex_held(p) ); p->nRef--; assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); #ifdef SQLITE_DEBUG if( p->trace ){ printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); } #endif pthread_mutex_unlock(&p->mutex); } /* ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are ** intended for use only inside assert() statements. On some platforms, ** there might be race conditions that can cause these routines to |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.379 2007/08/28 22:24:35 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 | /* ** Return the full pathname of the database file. */ const char *sqlite3PagerFilename(Pager *pPager){ return pPager->zFilename; } /* ** Return the directory of the database file. */ const char *sqlite3PagerDirname(Pager *pPager){ return pPager->zDirectory; } | > > > > > > > | 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 | /* ** Return the full pathname of the database file. */ const char *sqlite3PagerFilename(Pager *pPager){ return pPager->zFilename; } /* ** Return the VFS structure for the pager. */ const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ return pPager->pVfs; } /* ** Return the directory of the database file. */ const char *sqlite3PagerDirname(Pager *pPager){ return pPager->zDirectory; } |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite page cache ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** ** @(#) $Id: pager.h,v 1.63 2007/08/28 22:24:35 drh Exp $ */ #ifndef _PAGER_H_ #define _PAGER_H_ /* ** The type used to represent a page number. The first page in a file |
︙ | ︙ | |||
81 82 83 84 85 86 87 88 89 90 91 92 93 94 | int sqlite3PagerStmtCommit(Pager*); int sqlite3PagerStmtRollback(Pager*); void sqlite3PagerDontRollback(DbPage*); void sqlite3PagerDontWrite(DbPage*); int sqlite3PagerRefcount(Pager*); void sqlite3PagerSetSafetyLevel(Pager*,int,int); const char *sqlite3PagerFilename(Pager*); const char *sqlite3PagerDirname(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); void *sqlite3PagerGetData(DbPage *); void *sqlite3PagerGetExtra(DbPage *); int sqlite3PagerLockingMode(Pager *, int); | > | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | int sqlite3PagerStmtCommit(Pager*); int sqlite3PagerStmtRollback(Pager*); void sqlite3PagerDontRollback(DbPage*); void sqlite3PagerDontWrite(DbPage*); int sqlite3PagerRefcount(Pager*); void sqlite3PagerSetSafetyLevel(Pager*,int,int); const char *sqlite3PagerFilename(Pager*); const sqlite3_vfs *sqlite3PagerVfs(Pager*); const char *sqlite3PagerDirname(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); void *sqlite3PagerGetData(DbPage *); void *sqlite3PagerGetExtra(DbPage *); int sqlite3PagerLockingMode(Pager *, int); |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.112 2007/08/28 22:24:35 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
116 117 118 119 120 121 122 | int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int); int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeUsesBtree(Vdbe*, int, Btree*); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
328 329 330 331 332 333 334 335 336 337 338 339 340 341 | u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ u8 expired; /* True if the VM needs to be recompiled */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ int nChange; /* Number of db changes made since last reset */ i64 startTime; /* Time when query started - used for profiling */ BtreeMutexSet mtxSet; /* Set of Btree mutexes */ int nSql; /* Number of bytes in zSql */ char *zSql; /* Text of the SQL statement that generated this */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif int openedStatement; /* True if this VM has opened a statement journal */ | > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | u8 changeCntOn; /* True to update the change-counter */ u8 aborted; /* True if ROLLBACK in another VM causes an abort */ u8 expired; /* True if the VM needs to be recompiled */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ int nChange; /* Number of db changes made since last reset */ i64 startTime; /* Time when query started - used for profiling */ int btreeMask; /* Bitmask of db->aDb[] entries referenced */ BtreeMutexSet mtxSet; /* Set of Btree mutexes */ int nSql; /* Number of bytes in zSql */ char *zSql; /* Text of the SQL statement that generated this */ #ifdef SQLITE_DEBUG FILE *trace; /* Write an execution trace here, if not NULL */ #endif int openedStatement; /* True if this VM has opened a statement journal */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
655 656 657 658 659 660 661 | } assert( zP3!=0 ); return zP3; } #endif /* | | > | > > > > | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | } assert( zP3!=0 ); return zP3; } #endif /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** */ void sqlite3VdbeUsesBtree(Vdbe *p, int i, Btree *pBtree){ assert( i>=0 && i<p->db->nDb ); assert( i<sizeof(p->btreeMask)*8 ); assert( p->db->aDb[i].pBt==pBtree ); p->btreeMask |= 1<<i; sqlite3BtreeMutexSetInsert(&p->mtxSet, pBtree); } #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Print a single opcode. This routine is used for debugging only. |
︙ | ︙ | |||
1087 1088 1089 1090 1091 1092 1093 | ** (b) how many database files have open write transactions, not ** including the temp database. (b) is important because if more than ** one database file has an open write transaction, a master journal ** file is required for an atomic commit. */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; | | | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | ** (b) how many database files have open write transactions, not ** including the temp database. (b) is important because if more than ** one database file has an open write transaction, a master journal ** file is required for an atomic commit. */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( sqlite3BtreeIsInTrans(pBt) ){ needXcommit = 1; if( i!=1 ) nTrans++; } } /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 | ** and delete the master journal file. All the individual journal files ** still have 'null' as the master journal pointer, so they will roll ** back independently if a failure occurs. */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( i==1 ) continue; /* Ignore the TEMP database */ | | | 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 | ** and delete the master journal file. All the individual journal files ** still have 'null' as the master journal pointer, so they will roll ** back independently if a failure occurs. */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( i==1 ) continue; /* Ignore the TEMP database */ if( sqlite3BtreeIsInTrans(pBt) ){ char const *zFile = sqlite3BtreeGetJournalname(pBt); if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ needSync = 1; } rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset); offset += strlen(zFile)+1; |
︙ | ︙ | |||
1221 1222 1223 1224 1225 1226 1227 | ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the ** master journal file will be orphaned. But we cannot delete it, ** in case the master journal file name was written into the journal ** file before the failure occured. */ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; | | | 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 | ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the ** master journal file will be orphaned. But we cannot delete it, ** in case the master journal file name was written into the journal ** file before the failure occured. */ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); } } sqlite3OsCloseFree(pMaster); if( rc!=SQLITE_OK ){ sqlite3_free(zMaster); return rc; |
︙ | ︙ |
Changes to test/shared_err.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # # The focus of the tests in this file are IO errors that occur in a shared # cache context. What happens to connection B if one connection A encounters # an IO-error whilst reading or writing the file-system? # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # # The focus of the tests in this file are IO errors that occur in a shared # cache context. What happens to connection B if one connection A encounters # an IO-error whilst reading or writing the file-system? # # $Id: shared_err.test,v 1.13 2007/08/28 22:24:35 drh Exp $ proc skip {args} {} set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl |
︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | execsql {COMMIT} db2 set ::DB2 [sqlite3_connection_pointer db2] set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] sqlite3_step $::STMT ;# Cursor points at 000.000.000.000 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 } -tclbody { execsql { BEGIN; INSERT INTO t1 VALUES('201.201.201.201.201', NULL); UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; COMMIT; } } -cleanup { | > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | execsql {COMMIT} db2 set ::DB2 [sqlite3_connection_pointer db2] set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] sqlite3_step $::STMT ;# Cursor points at 000.000.000.000 sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 } -tclbody { btree_breakpoint execsql { BEGIN; INSERT INTO t1 VALUES('201.201.201.201.201', NULL); UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%'; COMMIT; } } -cleanup { |
︙ | ︙ |