SQLite

Check-in [b8cc493b47]
Login

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: b8cc493b47e618648f645ab73eb0253739e03fcd
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
Unified Diff Ignore Whitespace Patch
Changes to Makefile.in.
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

# 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 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/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 \







|

















>







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
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 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 \







|







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
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.412 2007/08/24 11:52:29 danielk1977 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"












|







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
1388
1389
1390
1391
1392
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
1420
1421
1422
1423
1424
1425
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
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  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)
/*
** 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;
    }
  }
}
#endif /* !SQLITE_OMIT_SHARED_CACHE */

/*
** Exit the recursive mutex on a Btree.
*/
#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
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;
    }
  }
}
#endif


#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);







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
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
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/*
** Return the full pathname of the underlying database file.
*/
const char *sqlite3BtreeGetFilename(Btree *p){
  assert( p->pBt->pPager!=0 );
  assert( sqlite3BtreeMutexHeld(p->pBt->mutex) );
  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 );
  assert( sqlite3BtreeMutexHeld(p->pBt->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.
*/
const char *sqlite3BtreeGetJournalname(Btree *p){
  assert( p->pBt->pPager!=0 );
  assert( sqlite3BtreeMutexHeld(p->pBt->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.







<








<










<







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
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808

#endif /* SQLITE_OMIT_VACUUM */

/*
** Return non-zero if a transaction is active.
*/
int sqlite3BtreeIsInTrans(Btree *p){
  assert( sqlite3BtreeMutexHeld(p->pBt->mutex) );
  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->pBt->mutex) );
  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







<

















<







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
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.86 2007/08/22 02:56:43 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_

/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/







|







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
25
26
27
28
29
30
31
32
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.438 2007/08/22 20:18:22 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.







|







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
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.602 2007/08/27 23:26:59 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
#include "sqliteLimit.h"

#define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */














|







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
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 "vdbe.h"
#include "btree.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.







|
|







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
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.644 2007/08/21 19:33:57 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <math.h>
#include "vdbeInt.h"

/*







|







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
688

689
690
691
692
693
694
695
696
697
698
  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 = SQLITE_BUSY;

    return SQLITE_BUSY;
  }
  return p->rc ? SQLITE_ERROR : SQLITE_DONE;
}

/* Opcode: Integer P1 * *
**
** The 32-bit integer value P1 is pushed onto the stack.
*/
case OP_Integer: {







|
>
|

|







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
1006

1007
1008
1009
1010
1011
1012
1013
  ** results from the stack when the statement returns.
  */
  p->resOnStack = 1;
  p->nCallback++;
  p->popStack = pOp->p1;
  p->pc = pc + 1;
  p->pTos = pTos;
  return SQLITE_ROW;

}

/* 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







|
>







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
2465
2466
2467
2468
2469
2470
2471
2472
2473

2474
2475
2476
2477
2478
2479
2480
      db->autoCommit = 1;
    }else{
      db->autoCommit = i;
      if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
        p->pTos = pTos;
        p->pc = pc;
        db->autoCommit = 1-i;
        p->rc = SQLITE_BUSY;
        return SQLITE_BUSY;
      }
    }
    if( p->rc==SQLITE_OK ){
      return SQLITE_DONE;
    }else{
      return SQLITE_ERROR;
    }

  }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;







|
|



|

|

>







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
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
  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 = SQLITE_BUSY;
      p->pTos = pTos;
      return SQLITE_BUSY;
    }
    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
      goto abort_due_to_error;
    }
  }
  break;
}







|

|







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
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
  }else{
    pCur->pKeyInfo = 0;
    pCur->pIncrKey = &pCur->bogusIncrKey;
  }
  switch( rc ){
    case SQLITE_BUSY: {
      p->pc = pc;
      p->rc = SQLITE_BUSY;
      p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
      return SQLITE_BUSY;
    }
    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







|

|







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
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.110 2007/05/08 21:45:28 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines







|







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
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
  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[100];   /* 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 */

  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







|














>







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){