Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Work toward correct btree locking in a multithreaded environment. (CVS 4307) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b8cc493b47e618648f645ab73eb02537 |
User & Date: | drh 2007-08-28 02:27:52.000 |
Context
2007-08-28
| ||
08:00 | Add some comments and test-cases for the global lru page list (used by sqlite3_release_memory()). (CVS 4308) (check-in: 0b80168895 user: danielk1977 tags: trunk) | |
02:27 | Work toward correct btree locking in a multithreaded environment. (CVS 4307) (check-in: b8cc493b47 user: drh tags: trunk) | |
2007-08-27
| ||
23:48 | Disable tests that debug on SQLITE_MEMDEBUG when that macro is not defined. (CVS 4306) (check-in: 741d6fb096 user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
116 117 118 119 120 121 122 | # You should not have to change anything below this line ############################################################################### TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1 # Object files for the SQLite library. # | | > | 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 | # You should not have to change anything below this line ############################################################################### TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1 # Object files for the SQLite library. # LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \ callback.lo complete.lo date.lo \ delete.lo expr.lo func.lo hash.lo journal.lo insert.lo loadext.lo \ main.lo malloc.lo mem1.lo mem2.lo mutex.lo \ opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ select.lo table.lo tokenize.lo trigger.lo update.lo \ util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \ where.lo utf.lo legacy.lo vtab.lo # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ $(TOP)/src/auth.c \ $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/build.c \ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ $(TOP)/src/date.c \ $(TOP)/src/delete.c \ |
︙ | ︙ | |||
335 336 337 338 339 340 341 342 343 344 345 346 347 348 | $(LTCOMPILE) -c $(TOP)/src/analyze.c attach.lo: $(TOP)/src/attach.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/attach.c auth.lo: $(TOP)/src/auth.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/auth.c btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h $(LTCOMPILE) -c $(TOP)/src/btree.c build.lo: $(TOP)/src/build.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/build.c | > > > | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | $(LTCOMPILE) -c $(TOP)/src/analyze.c attach.lo: $(TOP)/src/attach.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/attach.c auth.lo: $(TOP)/src/auth.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/auth.c btmutex.lo: $(TOP)/src/btmutex.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/btmutex.c btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h $(LTCOMPILE) -c $(TOP)/src/btree.c build.lo: $(TOP)/src/build.c $(HDR) $(LTCOMPILE) -c $(TOP)/src/build.c |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
51 52 53 54 55 56 57 | # This is how we compile # TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src # Object files for the SQLite library. # | | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | # This is how we compile # TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src # Object files for the SQLite library. # LIBOBJ+= alter.o analyze.o attach.o auth.o btmutex.o btree.o build.o \ callback.o complete.o date.o delete.o \ expr.o func.o hash.o insert.o journal.o loadext.o \ main.o malloc.o mem1.o mem2.o mutex.o \ opcodes.o os.o os_os2.o os_unix.o os_win.o \ pager.o parse.o pragma.o prepare.o printf.o random.o \ select.o table.o tclsqlite.o tokenize.o trigger.o \ update.o util.o vacuum.o \ |
︙ | ︙ | |||
87 88 89 90 91 92 93 94 95 96 97 98 99 100 | # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ $(TOP)/src/auth.c \ $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/build.c \ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ $(TOP)/src/date.c \ $(TOP)/src/delete.c \ | > | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | # All of the source code files. # SRC = \ $(TOP)/src/alter.c \ $(TOP)/src/analyze.c \ $(TOP)/src/attach.c \ $(TOP)/src/auth.c \ $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/btree.h \ $(TOP)/src/build.c \ $(TOP)/src/callback.c \ $(TOP)/src/complete.c \ $(TOP)/src/date.c \ $(TOP)/src/delete.c \ |
︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | parse.h \ sqlite3.h # Source code to the test files. # TESTSRC = \ $(TOP)/src/btree.c \ $(TOP)/src/date.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/malloc.c \ $(TOP)/src/os.c \ $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/printf.c \ | > > > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | parse.h \ sqlite3.h # Source code to the test files. # TESTSRC = \ $(TOP)/src/btmutex.c \ $(TOP)/src/btree.c \ $(TOP)/src/date.c \ $(TOP)/src/func.c \ $(TOP)/src/insert.c \ $(TOP)/src/malloc.c \ $(TOP)/src/mem1.c \ $(TOP)/src/mem2.c \ $(TOP)/src/mutex.c \ $(TOP)/src/os.c \ $(TOP)/src/os_os2.c \ $(TOP)/src/os_unix.c \ $(TOP)/src/os_win.c \ $(TOP)/src/pager.c \ $(TOP)/src/pragma.c \ $(TOP)/src/printf.c \ |
︙ | ︙ | |||
332 333 334 335 336 337 338 339 340 341 342 343 344 345 | $(TCCX) -c $(TOP)/src/analyze.c attach.o: $(TOP)/src/attach.c $(HDR) $(TCCX) -c $(TOP)/src/attach.c auth.o: $(TOP)/src/auth.c $(HDR) $(TCCX) -c $(TOP)/src/auth.c btree.o: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h $(TCCX) -c $(TOP)/src/btree.c build.o: $(TOP)/src/build.c $(HDR) $(TCCX) -c $(TOP)/src/build.c | > > > | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | $(TCCX) -c $(TOP)/src/analyze.c attach.o: $(TOP)/src/attach.c $(HDR) $(TCCX) -c $(TOP)/src/attach.c auth.o: $(TOP)/src/auth.c $(HDR) $(TCCX) -c $(TOP)/src/auth.c btmutex.o: $(TOP)/src/btmutex.c $(HDR) $(TOP)/src/btreeInt.h $(TCCX) -c $(TOP)/src/btmutex.c btree.o: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h $(TCCX) -c $(TOP)/src/btree.c build.o: $(TOP)/src/build.c $(HDR) $(TCCX) -c $(TOP)/src/build.c |
︙ | ︙ |
Added src/btmutex.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 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 194 195 196 197 198 199 | /* ** 2007 August 27 ** ** 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: btmutex.c,v 1.1 2007/08/28 02:27:52 drh Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too ** big and we want to break it down some. This packaged seemed like ** a good breakout. */ #include "btreeInt.h" #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) /* ** Enter a mutex on the given BTree object. ** ** If the object is not sharable, then no mutex is ever required ** and this routine is a no-op. The underlying mutex is non-recursive. ** But we keep a reference count in Btree.wantToLock so the behavior ** of this interface is recursive. ** ** To avoid deadlocks, multiple Btrees are locked in the same order ** by all database connections. The p->pNext is a list of other ** Btrees belonging to the same database connection as the p Btree ** which need to be locked after p. If we cannot get a lock on ** p, then first unlock all of the others on p->pNext, then wait ** for the lock to become available on p, then relock all of the ** subsequent Btrees that desire a lock. */ void sqlite3BtreeEnter(Btree *p){ Btree *pLater; /* Some basic sanity checking on the Btree. The list of Btrees ** connected by pNext and pPrev should be in sorted order by ** Btree.pBt value. All elements of the list should belong to ** the same connection. Only shared Btrees are on the list. */ assert( p->pNext==0 || p->pNext->pBt>p->pBt ); assert( p->pPrev==0 || p->pPrev->pBt<p->pBt ); assert( p->pNext==0 || p->pNext->pSqlite==p->pSqlite ); assert( p->pPrev==0 || p->pPrev->pSqlite==p->pSqlite ); assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); /* Check for locking consistency */ assert( !p->locked || p->wantToLock>0 ); assert( p->sharable || p->wantToLock==0 ); /* We should already hold a lock on the database connection */ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); if( !p->sharable ) return; p->wantToLock++; if( p->locked ) return; /* In most cases, we should be able to acquire the lock we ** want without having to go throught the ascending lock ** procedure that follows. Just be sure not to block. */ if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ p->locked = 1; return; } /* To avoid deadlock, first release all locks with a larger ** BtShared address. Then acquire our lock. Then reacquire ** the other BtShared locks that we used to hold in ascending ** order. */ for(pLater=p->pNext; pLater; pLater=pLater->pNext){ assert( pLater->sharable ); assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); assert( !pLater->locked || pLater->wantToLock>0 ); if( pLater->locked ){ sqlite3_mutex_leave(pLater->pBt->mutex); pLater->locked = 0; } } sqlite3_mutex_enter(p->pBt->mutex); for(pLater=p->pNext; pLater; pLater=pLater->pNext){ if( pLater->wantToLock ){ sqlite3_mutex_enter(pLater->pBt->mutex); pLater->locked = 1; } } } /* ** Exit the recursive mutex on a Btree. */ void sqlite3BtreeLeave(Btree *p){ if( p->sharable ){ assert( p->wantToLock>0 ); p->wantToLock--; if( p->wantToLock==0 ){ assert( p->locked ); sqlite3_mutex_leave(p->pBt->mutex); p->locked = 0; } } } /* ** Potentially dd a new Btree pointer to a BtreeMutexSet. ** Really only add the Btree if it can possibly be shared with ** another database connection. ** ** The Btrees are kept in sorted order by pBtree->pBt. That ** way when we go to enter all the mutexes, we can enter them ** in order without every having to backup and retry and without ** worrying about deadlock. ** ** The number of shared btrees will always be small (usually 0 or 1) ** so an insertion sort is an adequate algorithm here. */ void sqlite3BtreeMutexSetInsert(BtreeMutexSet *pSet, Btree *pBtree){ int i, j; BtShared *pBt; if( !pBtree->sharable ) return; #ifndef NDEBUG { for(i=0; i<pSet->nMutex; i++){ assert( pSet->aBtree[i]!=pBtree ); } } #endif assert( pSet->nMutex>=0 ); assert( pSet->nMutex<sizeof(pSet->aBtree)/sizeof(pSet->aBtree[0])-1 ); pBt = pBtree->pBt; for(i=0; i<pSet->nMutex; i++){ assert( pSet->aBtree[i]!=pBtree ); if( pSet->aBtree[i]->pBt>pBt ){ for(j=pSet->nMutex; j>i; j--){ pSet->aBtree[j] = pSet->aBtree[j-1]; } pSet->aBtree[i] = pBtree; return; } } pSet->aBtree[pSet->nMutex++] = pBtree; } /* ** Enter the mutex of every btree in the set. This routine is ** called at the beginning of sqlite3VdbeExec(). The mutexes are ** exited at the end of the same function. */ void sqlite3BtreeMutexSetEnter(BtreeMutexSet *pSet){ int i; for(i=0; i<pSet->nMutex; i++){ Btree *p = pSet->aBtree[i]; /* Some basic sanity checking */ assert( i==0 || pSet->aBtree[i-1]->pBt<p->pBt ); assert( !p->locked || p->wantToLock>0 ); assert( p->sharable ); /* We should already hold a lock on the database connection */ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); p->wantToLock++; if( !p->locked ){ sqlite3_mutex_enter(p->pBt->mutex); } } } /* ** Leave the mutex of every btree in the set. */ void sqlite3BtreeMutexSetLeave(BtreeMutexSet *pSet){ int i; for(i=0; i<pSet->nMutex; i++){ Btree *p = pSet->aBtree[i]; /* Some basic sanity checking */ assert( i==0 || pSet->aBtree[i-1]->pBt<p->pBt ); assert( p->locked ); assert( p->sharable ); assert( p->wantToLock>0 ); /* We should already hold a lock on the database connection */ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); p->wantToLock--; if( p->wantToLock==0 ){ sqlite3_mutex_leave(p->pBt->mutex); } } } #endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */ |
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.413 2007/08/28 02:27:52 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" |
︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 | if( p->pPrev ) p->pPrev->pNext = p->pNext; if( p->pNext ) p->pNext->pPrev = p->pPrev; #endif sqlite3_free(p); return SQLITE_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 | if( p->pPrev ) p->pPrev->pNext = p->pNext; if( p->pNext ) p->pNext->pPrev = p->pPrev; #endif sqlite3_free(p); return SQLITE_OK; } #if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) /* ** Short-cuts for entering and leaving mutexes on a cursor. */ static void cursorLeave(BtCursor *p){ sqlite3BtreeLeave(p->pBtree); |
︙ | ︙ | |||
6676 6677 6678 6679 6680 6681 6682 | #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); | < < < | 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 | #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. |
︙ | ︙ | |||
6776 6777 6778 6779 6780 6781 6782 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ | < < | 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 | #endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans==TRANS_WRITE)); } /* ** Return non-zero if a statement transaction is active. */ int sqlite3BtreeIsInStmt(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p->pBt && p->pBt->inStmt); } /* ** Return non-zero if a read (or write) transaction is active. */ int sqlite3BtreeIsInReadTrans(Btree *p){ assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans!=TRANS_NONE)); } /* ** This function returns a pointer to a blob of memory associated with ** a single shared-btree. The memory is used by client code for it's own |
︙ | ︙ |
Changes to src/btree.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 B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 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 B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.87 2007/08/28 02:27:52 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* TODO: This definition is just included so other modules compile. It ** needs to be revisited. */ |
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ sqlite3 *db, /* Associated database connection */ Btree **, /* Return open Btree* here */ int flags /* Flags */ | > > > > > > > > > > > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | /* ** Forward declarations of structure */ typedef struct Btree Btree; typedef struct BtCursor BtCursor; typedef struct BtShared BtShared; typedef struct BtreeMutexSet BtreeMutexSet; /* ** This structure records all of the Btrees that need to hold ** a mutex before we enter sqlite3VdbeExec(). The Btrees are ** are placed in aBtree[] in order of aBtree[]->pBt. That way, ** we can always lock and unlock them all quickly. */ struct BtreeMutexSet { int nMutex; Btree *aBtree[SQLITE_MAX_ATTACHED+1]; }; int sqlite3BtreeOpen( const char *zFilename, /* Name of database file to open */ sqlite3 *db, /* Associated database connection */ Btree **, /* Return open Btree* here */ int flags /* Flags */ |
︙ | ︙ | |||
165 166 167 168 169 170 171 172 173 | void sqlite3BtreeCacheOverflow(BtCursor *); #ifdef SQLITE_TEST int sqlite3BtreeCursorInfo(BtCursor*, int*, int); void sqlite3BtreeCursorList(Btree*); int sqlite3BtreePageDump(Btree*, int, int recursive); #endif #endif /* _BTREE_H_ */ | > > > > > > > > > > > > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | void sqlite3BtreeCacheOverflow(BtCursor *); #ifdef SQLITE_TEST int sqlite3BtreeCursorInfo(BtCursor*, int*, int); void sqlite3BtreeCursorList(Btree*); int sqlite3BtreePageDump(Btree*, int, int recursive); #endif #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE void sqlite3BtreeMutexSetEnter(BtreeMutexSet*); void sqlite3BtreeMutexSetLeave(BtreeMutexSet*); void sqlite3BtreeMutexSetInsert(BtreeMutexSet*, Btree*); #else # define sqlite3BtreeMutexSetEnter(X) # define sqlite3BtreeMutexSetLeave(X) # define sqlite3BtreeMutexSetInsert(X,Y) #endif #endif /* _BTREE_H_ */ |
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.439 2007/08/28 02:27:52 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 167 168 169 170 171 172 173 | */ 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; 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); | > | 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; sqlite3VdbeAddMutexBtree(v, 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/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.603 2007/08/28 02:27:52 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "sqliteLimit.h" #define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ |
︙ | ︙ | |||
229 230 231 232 233 234 235 | int nBusy; /* Incremented with each busy call */ }; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler typedefs. */ | | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | int nBusy; /* Incremented with each busy call */ }; /* ** Defer sourcing vdbe.h and btree.h until after the "u8" and ** "BusyHandler typedefs. */ #include "btree.h" #include "vdbe.h" #include "pager.h" /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.645 2007/08/28 02:27:52 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include <math.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
461 462 463 464 465 466 467 468 469 470 471 472 473 474 | #ifndef NDEBUG Mem *pStackLimit; #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); pTos = p->pTos; if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; | > | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | #ifndef NDEBUG Mem *pStackLimit; #endif if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); pTos = p->pTos; sqlite3BtreeMutexSetEnter(&p->mtxSet); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; |
︙ | ︙ | |||
681 682 683 684 685 686 687 | p->errorAction = pOp->p2; if( pOp->p3 ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); if( rc==SQLITE_BUSY ){ | | > | | | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 | p->errorAction = pOp->p2; if( pOp->p3 ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); } rc = sqlite3VdbeHalt(p); assert( rc==SQLITE_BUSY || rc==SQLITE_OK ); if( rc==SQLITE_BUSY ){ p->rc = rc = SQLITE_BUSY; }else{ rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; } /* Opcode: Integer P1 * * ** ** The 32-bit integer value P1 is pushed onto the stack. */ case OP_Integer: { |
︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 | ** results from the stack when the statement returns. */ p->resOnStack = 1; p->nCallback++; p->popStack = pOp->p1; p->pc = pc + 1; p->pTos = pTos; | | > | 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 | ** results from the stack when the statement returns. */ p->resOnStack = 1; p->nCallback++; p->popStack = pOp->p1; p->pc = pc + 1; p->pTos = pTos; rc = SQLITE_ROW; goto vdbe_return; } /* Opcode: Concat P1 P2 * ** ** Look at the first P1+2 elements of the stack. Append them all ** together with the lowest element first. The original P1+2 elements ** are popped from the stack if P2==0 and retained if P2==1. If |
︙ | ︙ | |||
2458 2459 2460 2461 2462 2463 2464 | db->autoCommit = 1; }else{ db->autoCommit = i; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pTos = pTos; p->pc = pc; db->autoCommit = 1-i; | | | | | > | 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 | db->autoCommit = 1; }else{ db->autoCommit = i; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pTos = pTos; p->pc = pc; db->autoCommit = 1-i; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } } if( p->rc==SQLITE_OK ){ rc = SQLITE_DONE; }else{ rc = SQLITE_ERROR; } goto vdbe_return; }else{ sqlite3SetString(&p->zErrMsg, (!i)?"cannot start a transaction within a transaction":( (rollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active"), (char*)0); rc = SQLITE_ERROR; |
︙ | ︙ | |||
2509 2510 2511 2512 2513 2514 2515 | assert( i>=0 && i<db->nDb ); pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; | | | | 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 | assert( i>=0 && i<db->nDb ); pBt = db->aDb[i].pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2); if( rc==SQLITE_BUSY ){ p->pc = pc; p->rc = rc = SQLITE_BUSY; p->pTos = pTos; goto vdbe_return; } if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){ goto abort_due_to_error; } } break; } |
︙ | ︙ | |||
2751 2752 2753 2754 2755 2756 2757 | }else{ pCur->pKeyInfo = 0; pCur->pIncrKey = &pCur->bogusIncrKey; } switch( rc ){ case SQLITE_BUSY: { p->pc = pc; | | | | 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 | }else{ pCur->pKeyInfo = 0; pCur->pIncrKey = &pCur->bogusIncrKey; } switch( rc ){ case SQLITE_BUSY: { p->pc = pc; p->rc = rc = SQLITE_BUSY; p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */ goto vdbe_return; } case SQLITE_OK: { int flags = sqlite3BtreeFlags(pCur->pCursor); /* Sanity checking. Only the lower four bits of the flags byte should ** be used. Bit 3 (mask 0x08) is unpreditable. The lower 3 bits ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or ** 2 (zerodata for indices). If these conditions are not met it can |
︙ | ︙ | |||
5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 | p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); p->pTos = pTos; return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. */ too_big: sqlite3SetString(&p->zErrMsg, "string or blob too big", (char*)0); | > > > > > > | 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 | p->rc = rc; rc = SQLITE_ERROR; }else{ rc = SQLITE_DONE; } sqlite3VdbeHalt(p); p->pTos = pTos; /* This is the only way out of this procedure. We have to ** release the mutexes on btrees that were acquired at the ** top. */ vdbe_return: sqlite3BtreeMutexSetLeave(&p->mtxSet); return rc; /* Jump to here if a string or blob larger than SQLITE_MAX_LENGTH ** is encountered. */ too_big: sqlite3SetString(&p->zErrMsg, "string or blob too big", (char*)0); |
︙ | ︙ |
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.111 2007/08/28 02:27:52 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 123 124 125 126 127 128 129 | 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); 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*); | > | 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 sqlite3VdbeAddMutexBtree(Vdbe*, 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.
︙ | ︙ | |||
313 314 315 316 317 318 319 | int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int inTempTrans; /* True if temp database is transactioned */ | | > | 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 | int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ int inTempTrans; /* True if temp database is transactioned */ int returnStack[25]; /* Return address stack for OP_Gosub & OP_Return */ int returnDepth; /* Next unused element in returnStack[] */ int nResColumn; /* Number of columns in one row of the result set */ char **azResColumn; /* Values for one row of result */ int popStack; /* Pop the stack this much on entry to VdbeExec() */ char *zErrMsg; /* Error message written here */ u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ 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 */ #ifdef SQLITE_SSE |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
653 654 655 656 657 658 659 660 661 662 663 664 665 666 | } } } assert( zP3!=0 ); return zP3; } #endif #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Print a single opcode. This routine is used for debugging only. */ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ | > > > > > > > | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | } } } assert( zP3!=0 ); return zP3; } #endif /* ** Add a btree to the set of btrees that might need a mutex. */ void sqlite3VdbeAddMutexBtree(Vdbe *p, Btree *pBtree){ sqlite3BtreeMutexSetInsert(&p->mtxSet, pBtree); } #if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Print a single opcode. This routine is used for debugging only. */ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ |
︙ | ︙ |