/ Check-in [cb1f11cd]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add some test logic to the new memory allocation subsystem. (Lots more needed.) The test suite is currently indicating memory leaks, though it is unclear if this is a true code problem or just an instrumentation problem. (CVS 5240)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb1f11cd9764cf0275e88e1f6342e366e5536bfd
User & Date: drh 2008-06-19 00:16:08
Context
2008-06-19
01:03
Bug fixes: Plug a memory leak introduced by the previous check-in. Get the amalgamation to the point where it will compile. (CVS 5241) check-in: 005f8eae user: drh tags: trunk
00:16
Add some test logic to the new memory allocation subsystem. (Lots more needed.) The test suite is currently indicating memory leaks, though it is unclear if this is a true code problem or just an instrumentation problem. (CVS 5240) check-in: cb1f11cd user: drh tags: trunk
2008-06-18
21:08
fix OS/2 files to compile again (looking at Windows equivalents for guidance) (CVS 5239) check-in: 8b14a220 user: pweilbacher tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Makefile.in.

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
222
223
224
225
226
227
228

229
230
231
232
233
234
235
...
605
606
607
608
609
610
611



612
613
614
615
616
617
618
        btree.lo build.lo callback.lo complete.lo date.lo \
        delete.lo expr.lo fault.lo func.lo global.lo \
        hash.lo journal.lo insert.lo loadext.lo \
        main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mutex.lo \
        mutex_os2.lo mutex_unix.lo mutex_w32.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

# Object files for the amalgamation.
#
OBJS1 = sqlite3.lo
................................................................................
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/select.c \

  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqlite3ext.h \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/table.c \
  $(TOP)/src/tclsqlite.c \
................................................................................
	$(LTCOMPILE) -c $(TOP)/src/printf.c

random.lo:	$(TOP)/src/random.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/random.c

select.lo:	$(TOP)/src/select.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/select.c




sqlite3.h:	$(TOP)/src/sqlite.h.in 
	sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \
	sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h

table.lo:	$(TOP)/src/table.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/table.c







|







 







>







 







>
>
>







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
        btree.lo build.lo callback.lo complete.lo date.lo \
        delete.lo expr.lo fault.lo func.lo global.lo \
        hash.lo journal.lo insert.lo loadext.lo \
        main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mem5.lo mutex.lo \
        mutex_os2.lo mutex_unix.lo mutex_w32.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 status.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

# Object files for the amalgamation.
#
OBJS1 = sqlite3.lo
................................................................................
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/select.c \
  $(TOP)/src/status.c \
  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqlite3ext.h \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/table.c \
  $(TOP)/src/tclsqlite.c \
................................................................................
	$(LTCOMPILE) -c $(TOP)/src/printf.c

random.lo:	$(TOP)/src/random.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/random.c

select.lo:	$(TOP)/src/select.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/select.c

status.lo:	$(TOP)/src/status.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/status.c

sqlite3.h:	$(TOP)/src/sqlite.h.in 
	sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \
	sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h

table.lo:	$(TOP)/src/table.c $(HDR)
	$(LTCOMPILE) -c $(TOP)/src/table.c

Changes to main.mk.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
129
130
131
132
133
134
135

136
137
138
139
140
141
142
LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o date.o delete.o \
         expr.o fault.o func.o global.o hash.o insert.o journal.o loadext.o \
         main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o \
         mutex.o mutex_os2.o mutex_unix.o mutex_w32.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 $(TCLOBJ) tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o rtree.o

EXTOBJ = icu.o
EXTOBJ += fts1.o \
	  fts1_hash.o \
................................................................................
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/select.c \

  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqlite3ext.h \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/table.c \
  $(TOP)/src/tclsqlite.c \







|







 







>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
LIBOBJ+= alter.o analyze.o attach.o auth.o bitvec.o btmutex.o btree.o build.o \
         callback.o complete.o date.o delete.o \
         expr.o fault.o func.o global.o hash.o insert.o journal.o loadext.o \
         main.o malloc.o mem1.o mem2.o mem3.o mem4.o mem5.o \
         mutex.o mutex_os2.o mutex_unix.o mutex_w32.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 status.o table.o $(TCLOBJ) tokenize.o trigger.o \
         update.o util.o vacuum.o \
         vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \
         where.o utf.o legacy.o vtab.o rtree.o

EXTOBJ = icu.o
EXTOBJ += fts1.o \
	  fts1_hash.o \
................................................................................
  $(TOP)/src/pager.h \
  $(TOP)/src/parse.y \
  $(TOP)/src/pragma.c \
  $(TOP)/src/prepare.c \
  $(TOP)/src/printf.c \
  $(TOP)/src/random.c \
  $(TOP)/src/select.c \
  $(TOP)/src/status.c \
  $(TOP)/src/shell.c \
  $(TOP)/src/sqlite.h.in \
  $(TOP)/src/sqlite3ext.h \
  $(TOP)/src/sqliteInt.h \
  $(TOP)/src/sqliteLimit.h \
  $(TOP)/src/table.c \
  $(TOP)/src/tclsqlite.c \

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1395
1396
1397
1398
1399
1400
1401


















1402
1403
1404
1405
1406
1407
1408
....
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
....
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
....
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
....
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
....
6639
6640
6641
6642
6643
6644
6645
6646
6647

6648
6649
6650
6651
6652
6653
6654
....
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
** 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.466 2008/06/18 17:09:10 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"

................................................................................
  }
  sqlite3_mutex_leave(pMaster);
  return removed;
#else
  return 1;
#endif
}



















/*
** Close an open database and invalidate all cursors.
*/
int sqlite3BtreeClose(Btree *p){
  BtShared *pBt = p->pBt;
  BtCursor *pCur;
................................................................................
    */
    assert( !pBt->pCursor );
    sqlite3PagerClose(pBt->pPager);
    if( pBt->xFreeSchema && pBt->pSchema ){
      pBt->xFreeSchema(pBt->pSchema);
    }
    sqlite3_free(pBt->pSchema);
    sqlite3_free(pBt->pTmpSpace);
    sqlite3_free(pBt);
  }

#ifndef SQLITE_OMIT_SHARED_CACHE
  assert( p->wantToLock==0 );
  assert( p->locked==0 );
  if( p->pPrev ) p->pPrev->pNext = p->pNext;
  if( p->pNext ) p->pNext->pPrev = p->pPrev;
................................................................................
    nReserve = pBt->pageSize - pBt->usableSize;
  }
  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
        ((pageSize-1)&pageSize)==0 ){
    assert( (pageSize & 7)==0 );
    assert( !pBt->pPage1 && !pBt->pCursor );
    pBt->pageSize = pageSize;
    sqlite3_free(pBt->pTmpSpace);
    pBt->pTmpSpace = 0;
    rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
  }
  pBt->usableSize = pBt->pageSize - nReserve;
  sqlite3BtreeLeave(p);
  return rc;
}

................................................................................
      ** actually pageSize. Unlock the database, leave pBt->pPage1 at
      ** zero and return SQLITE_OK. The caller will call this function
      ** again with the correct page-size.
      */
      releasePage(pPage1);
      pBt->usableSize = usableSize;
      pBt->pageSize = pageSize;
      sqlite3_free(pBt->pTmpSpace);
      pBt->pTmpSpace = 0;
      sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
      return SQLITE_OK;
    }
    if( usableSize<500 ){
      goto page1_init_failed;
    }
    pBt->pageSize = pageSize;
................................................................................
        return SQLITE_LOCKED;
      }
    }
  }
  return SQLITE_OK;
}

/*
** Make sure pBt->pTmpSpace points to an allocation of 
** MX_CELL_SIZE(pBt) bytes.
*/
static void allocateTempSpace(BtShared *pBt){
  if( !pBt->pTmpSpace ){
    pBt->pTmpSpace = sqlite3Malloc(MX_CELL_SIZE(pBt));
  }
}

/*
** Insert a new record into the BTree.  The key is given by (pKey,nKey)
** and the data is given by (pData,nData).  The cursor is used only to
** define what table the record should be inserted into.  The cursor
** is left pointing at a random location.
**
** For an INTKEY table, only the nKey value of the key is used.  pKey is
................................................................................
    checkTreePage(pCheck, pgno, pPage, zContext);
  }
 
  /* Check for complete coverage of the page
  */
  data = pPage->aData;
  hdr = pPage->hdrOffset;
  hit = sqlite3MallocZero( usableSize );
  if( hit ){

    memset(hit, 1, get2byte(&data[hdr+5]));
    nCell = get2byte(&data[hdr+3]);
    cellStart = hdr + 12 - 4*pPage->leaf;
    for(i=0; i<nCell; i++){
      int pc = get2byte(&data[cellStart+i*2]);
      u16 size = cellSizePtr(pPage, &data[pc]);
      int j;
................................................................................
    }
    if( cnt!=data[hdr+7] ){
      checkAppendMsg(pCheck, 0, 
          "Fragmented space is %d byte reported as %d on page %d",
          cnt, data[hdr+7], iPage);
    }
  }
  sqlite3_free(hit);

  releasePage(pPage);
  return depth+1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<







 







<
|







 







<
|







 







<
<
<
<
<
<
<
<
<
<







 







|

>







 







|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
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
....
1458
1459
1460
1461
1462
1463
1464
1465

1466
1467
1468
1469
1470
1471
1472
....
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1576
....
1710
1711
1712
1713
1714
1715
1716

1717
1718
1719
1720
1721
1722
1723
1724
....
5688
5689
5690
5691
5692
5693
5694










5695
5696
5697
5698
5699
5700
5701
....
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
....
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
** 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.467 2008/06/19 00:16:08 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"

................................................................................
  }
  sqlite3_mutex_leave(pMaster);
  return removed;
#else
  return 1;
#endif
}

/*
** Make sure pBt->pTmpSpace points to an allocation of 
** MX_CELL_SIZE(pBt) bytes.
*/
static void allocateTempSpace(BtShared *pBt){
  if( !pBt->pTmpSpace ){
    pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
  }
}

/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
  sqlite3PageFree( pBt->pTmpSpace);
  pBt->pTmpSpace = 0;
}

/*
** Close an open database and invalidate all cursors.
*/
int sqlite3BtreeClose(Btree *p){
  BtShared *pBt = p->pBt;
  BtCursor *pCur;
................................................................................
    */
    assert( !pBt->pCursor );
    sqlite3PagerClose(pBt->pPager);
    if( pBt->xFreeSchema && pBt->pSchema ){
      pBt->xFreeSchema(pBt->pSchema);
    }
    sqlite3_free(pBt->pSchema);
    freeTempSpace(pBt);

  }

#ifndef SQLITE_OMIT_SHARED_CACHE
  assert( p->wantToLock==0 );
  assert( p->locked==0 );
  if( p->pPrev ) p->pPrev->pNext = p->pNext;
  if( p->pNext ) p->pNext->pPrev = p->pPrev;
................................................................................
    nReserve = pBt->pageSize - pBt->usableSize;
  }
  if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
        ((pageSize-1)&pageSize)==0 ){
    assert( (pageSize & 7)==0 );
    assert( !pBt->pPage1 && !pBt->pCursor );
    pBt->pageSize = pageSize;

    freeTempSpace(pBt);
    rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
  }
  pBt->usableSize = pBt->pageSize - nReserve;
  sqlite3BtreeLeave(p);
  return rc;
}

................................................................................
      ** actually pageSize. Unlock the database, leave pBt->pPage1 at
      ** zero and return SQLITE_OK. The caller will call this function
      ** again with the correct page-size.
      */
      releasePage(pPage1);
      pBt->usableSize = usableSize;
      pBt->pageSize = pageSize;

      freeTempSpace(pBt);
      sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
      return SQLITE_OK;
    }
    if( usableSize<500 ){
      goto page1_init_failed;
    }
    pBt->pageSize = pageSize;
................................................................................
        return SQLITE_LOCKED;
      }
    }
  }
  return SQLITE_OK;
}











/*
** Insert a new record into the BTree.  The key is given by (pKey,nKey)
** and the data is given by (pData,nData).  The cursor is used only to
** define what table the record should be inserted into.  The cursor
** is left pointing at a random location.
**
** For an INTKEY table, only the nKey value of the key is used.  pKey is
................................................................................
    checkTreePage(pCheck, pgno, pPage, zContext);
  }
 
  /* Check for complete coverage of the page
  */
  data = pPage->aData;
  hdr = pPage->hdrOffset;
  hit = sqlite3PageMalloc( pBt->pageSize );
  if( hit ){
    memset(hit, 0, usableSize );
    memset(hit, 1, get2byte(&data[hdr+5]));
    nCell = get2byte(&data[hdr+3]);
    cellStart = hdr + 12 - 4*pPage->leaf;
    for(i=0; i<nCell; i++){
      int pc = get2byte(&data[cellStart+i*2]);
      u16 size = cellSizePtr(pPage, &data[pc]);
      int j;
................................................................................
    }
    if( cnt!=data[hdr+7] ){
      checkAppendMsg(pCheck, 0, 
          "Fragmented space is %d byte reported as %d on page %d",
          cnt, data[hdr+7], iPage);
    }
  }
  sqlite3PageFree(hit);

  releasePage(pPage);
  return depth+1;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

#ifndef SQLITE_OMIT_INTEGRITY_CHECK

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
76
77
78
79
80
81
82

83
84
85
86
87
88
89
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.450 2008/06/18 18:57:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
  if( sqlite3IsInit ) return SQLITE_OK;
  rc = sqlite3MutexInit();
  if( rc==SQLITE_OK ){
    sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex_enter(pMutex);
    if( sqlite3IsInit==0 ){
      sqlite3IsInit = 1;

      if( rc==SQLITE_OK ) rc = sqlite3MallocInit();
      if( rc==SQLITE_OK ) rc = sqlite3_os_init();
      if( rc!=SQLITE_OK ){
        sqlite3IsInit = 0;
      }else{
        sqlite3FullInit = 1;
      }







|







 







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.451 2008/06/19 00:16:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
................................................................................
  if( sqlite3IsInit ) return SQLITE_OK;
  rc = sqlite3MutexInit();
  if( rc==SQLITE_OK ){
    sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex_enter(pMutex);
    if( sqlite3IsInit==0 ){
      sqlite3IsInit = 1;
      sqlite3StatusReset();
      if( rc==SQLITE_OK ) rc = sqlite3MallocInit();
      if( rc==SQLITE_OK ) rc = sqlite3_os_init();
      if( rc!=SQLITE_OK ){
        sqlite3IsInit = 0;
      }else{
        sqlite3FullInit = 1;
      }

Changes to src/malloc.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139

140
141
142
143
144
145
146
...
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
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214





























215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
...
291
292
293
294
295
296
297
298
299
300



301
302
303
304


305
306
307

308

309
310












311






312
313
314
315
316
317
318
319
...
320
321
322
323
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
359
...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
...
385
386
387
388
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
** $Id: malloc.c,v 1.20 2008/06/18 18:12:04 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** This routine runs when the memory allocator sees that the
................................................................................
  */
  u32 *aScratchFree;
  u32 *aPageFree;

  /* Number of free pages for scratch and page-cache memory */
  u32 nScratchFree;
  u32 nPageFree;

  /*
  ** Performance statistics
  */
  sqlite3_int64 nowUsed;  /* Main memory currently in use */
  sqlite3_int64 mxUsed;   /* Highwater mark for nowUsed */
  int mxReq;              /* Max request size for ordinary mallocs */
  int mxScratchReq;       /* Max request size for xTemp mallocs */
} mem0;

/*
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  if( sqlite3Config.m.xMalloc==0 ){
................................................................................
    int i;
    mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
                  [sqlite3Config.szScratch*sqlite3Config.nScratch];
    for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
    mem0.nScratchFree = sqlite3Config.nScratch;
  }else{
    sqlite3Config.pScratch = 0;

  }
  if( sqlite3Config.pPage && sqlite3Config.szPage>=512
      && sqlite3Config.nPage>0 ){
    int i;
    mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
                  [sqlite3Config.szPage*sqlite3Config.nPage];
    for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
    mem0.nPageFree = sqlite3Config.nPage;
  }else{
    sqlite3Config.pPage = 0;

  }
  return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
}

/*
** Deinitialize the memory allocation subsystem.
*/
................................................................................
  memset(&mem0, 0, sizeof(mem0));
}

/*
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
  sqlite3_int64 n;
  sqlite3_initialize();
  sqlite3_mutex_enter(mem0.mutex);
  n = mem0.nowUsed;
  sqlite3_mutex_leave(mem0.mutex);  
  return n;
}

/*
** Return the maximum amount of memory that has ever been
** checked out since either the beginning of this process
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
  sqlite3_int64 n;
  sqlite3_initialize();
  sqlite3_mutex_enter(mem0.mutex);
  n = mem0.mxUsed;
  if( resetFlag ){
    mem0.mxUsed = mem0.nowUsed;
  }
  sqlite3_mutex_leave(mem0.mutex);  
  return n;
}

/*
** Change the alarm callback
*/
int sqlite3_memory_alarm(
  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
................................................................................
static void sqlite3MallocAlarm(int nByte){
  void (*xCallback)(void*,sqlite3_int64,int);
  sqlite3_int64 nowUsed;
  void *pArg;
  if( mem0.alarmCallback==0 || mem0.alarmBusy  ) return;
  mem0.alarmBusy = 1;
  xCallback = mem0.alarmCallback;
  nowUsed = mem0.nowUsed;
  pArg = mem0.alarmArg;
  sqlite3_mutex_leave(mem0.mutex);
  xCallback(pArg, nowUsed, nByte);
  sqlite3_mutex_enter(mem0.mutex);
  mem0.alarmBusy = 0;
}































/*
** Allocate memory.  This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
void *sqlite3Malloc(int n){
  void *p;
  int nFull;
  if( n<=0 ){
    return 0;
  }else if( sqlite3Config.bMemstat ){
    nFull = sqlite3Config.m.xRoundup(n);
    sqlite3_mutex_enter(mem0.mutex);
    if( n>mem0.mxReq ) mem0.mxReq = n;
    if( mem0.alarmCallback!=0 && mem0.nowUsed+nFull>=mem0.alarmThreshold ){
      sqlite3MallocAlarm(nFull);
    }
    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
      p = 0;
    }else{
      p = sqlite3Config.m.xMalloc(nFull);
      if( p==0 ){
        sqlite3MallocAlarm(nFull);
        p = malloc(nFull);
      }
    }
    if( p ){
      mem0.nowUsed += nFull;
      if( mem0.nowUsed>mem0.mxUsed ){
        mem0.mxUsed = mem0.nowUsed;
      }
    }

    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = sqlite3Config.m.xMalloc(n);
  }
  return p;
}

................................................................................

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
  /* Verify that no more than one scratch allocation per thread
  ** is outstanding at one time.  (This is only checked in the
  ** single-threaded case since checking in the multi-threaded case
  ** would be much more complicated.) */
  assert( scratchAllocOut==0 );
  scratchAllocOut = 1;
#endif




  sqlite3_mutex_enter(mem0.mutex);
  if( n>mem0.mxScratchReq ) mem0.mxScratchReq = n;
  if( mem0.nScratchFree==0 || sqlite3Config.szScratch>=n ){
    p = sqlite3Config.m.xMalloc(n);


  }else{
    int i;
    i = mem0.aScratchFree[--mem0.nScratchFree];

    i *= sqlite3Config.szScratch;

    p = (void*)&((char*)sqlite3Config.pScratch)[i];
  }












  sqlite3_mutex_leave(mem0.mutex);






  return p;
}
void sqlite3ScratchFree(void *p){
  if( p ){

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
    /* Verify that no more than one scratch allocation per thread
    ** is outstanding at one time.  (This is only checked in the
................................................................................
    ** single-threaded case since checking in the multi-threaded case
    ** would be much more complicated.) */
    assert( scratchAllocOut==1 );
    scratchAllocOut = 0;
#endif

    if( sqlite3Config.pScratch==0
       || p<sqlite3Config.pScratch
       || p>=(void*)mem0.aScratchFree ){





      sqlite3Config.m.xFree(p);

    }else{



      int i;
      sqlite3_mutex_enter(mem0.mutex);
      assert( mem0.nScratchFree<sqlite3Config.nScratch );
      i = p - sqlite3Config.pScratch;
      i /= sqlite3Config.szScratch;
      assert( i>=0 && i<sqlite3Config.nScratch );


      mem0.aScratchFree[mem0.nScratchFree++] = i;

      sqlite3_mutex_leave(mem0.mutex);
    }
  }
}

/*
** Place holders for the page-cache memory allocator.




*/
void *sqlite3PageMalloc(int iSize){





  return sqlite3Malloc(iSize);
}






























void sqlite3PageFree(void *pOld){
  sqlite3_free(pOld);













}














/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
int sqlite3MallocSize(void *p){
  return sqlite3Config.m.xSize(p);
}
................................................................................
/*
** Free memory previously obtained from sqlite3Malloc().
*/
void sqlite3_free(void *p){
  if( p==0 ) return;
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    mem0.nowUsed -= sqlite3MallocSize(p);
    sqlite3Config.m.xFree(p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    sqlite3Config.m.xFree(p);
  }
}

................................................................................
  if( nBytes<=0 ){
    sqlite3_free(pOld);
    return 0;
  }
  nOld = sqlite3MallocSize(pOld);
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    if( nBytes>mem0.mxReq ) mem0.mxReq = nBytes;
    nNew = sqlite3Config.m.xRoundup(nBytes);
    if( nOld==nNew ){
      pNew = pOld;
    }else{

      if( mem0.nowUsed+nNew-nOld>=mem0.alarmThreshold ){
        sqlite3MallocAlarm(nNew-nOld);
      }
      if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
        pNew = 0;
      }else{
        pNew = sqlite3Config.m.xRealloc(pOld, nNew);
        if( pNew==0 ){
          sqlite3MallocAlarm(nBytes);
          pNew = sqlite3Config.m.xRealloc(pOld, nNew);
        }
      }
      if( pNew ){
        mem0.nowUsed += nNew-nOld;
        if( mem0.nowUsed>mem0.mxUsed ){
          mem0.mxUsed = mem0.nowUsed;
        }
      }
    }
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
  }
  return pNew;







|







 







<
<
<
<
<
<
<
<







 







>










>







 







|
|
<
<
<
|








|
|
<
<
<
<
<
<
|







 







|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







<

|

<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







 







<


>
>
>
|
<
|
<
>
>
|
|
|
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|







 







|
|
>
>
>
>
>
|
>
|
>
>
>

<
<



>
>

>






<
>
>
>
>

|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>







 







|







 







|




>
|












|
<
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
93
94
95
96
97
98
99








100
101
102
103
104
105
106
...
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
...
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
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

236
237
238

239



















240
241
242
243
244
245
246
247
...
285
286
287
288
289
290
291

292
293
294
295
296
297

298

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
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
359
360
361
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500



501
502
503
504
505
506
507
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
** $Id: malloc.c,v 1.21 2008/06/19 00:16:08 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** This routine runs when the memory allocator sees that the
................................................................................
  */
  u32 *aScratchFree;
  u32 *aPageFree;

  /* Number of free pages for scratch and page-cache memory */
  u32 nScratchFree;
  u32 nPageFree;








} mem0;

/*
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  if( sqlite3Config.m.xMalloc==0 ){
................................................................................
    int i;
    mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
                  [sqlite3Config.szScratch*sqlite3Config.nScratch];
    for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
    mem0.nScratchFree = sqlite3Config.nScratch;
  }else{
    sqlite3Config.pScratch = 0;
    sqlite3Config.szScratch = 0;
  }
  if( sqlite3Config.pPage && sqlite3Config.szPage>=512
      && sqlite3Config.nPage>0 ){
    int i;
    mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
                  [sqlite3Config.szPage*sqlite3Config.nPage];
    for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
    mem0.nPageFree = sqlite3Config.nPage;
  }else{
    sqlite3Config.pPage = 0;
    sqlite3Config.szPage = 0;
  }
  return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
}

/*
** Deinitialize the memory allocation subsystem.
*/
................................................................................
  memset(&mem0, 0, sizeof(mem0));
}

/*
** Return the amount of memory currently checked out.
*/
sqlite3_int64 sqlite3_memory_used(void){
  int n, mx;
  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);



  return (sqlite3_int64)n;
}

/*
** Return the maximum amount of memory that has ever been
** checked out since either the beginning of this process
** or since the most recent reset.
*/
sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
  int n, mx;
  sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);






  return (sqlite3_int64)mx;
}

/*
** Change the alarm callback
*/
int sqlite3_memory_alarm(
  void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
................................................................................
static void sqlite3MallocAlarm(int nByte){
  void (*xCallback)(void*,sqlite3_int64,int);
  sqlite3_int64 nowUsed;
  void *pArg;
  if( mem0.alarmCallback==0 || mem0.alarmBusy  ) return;
  mem0.alarmBusy = 1;
  xCallback = mem0.alarmCallback;
  nowUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
  pArg = mem0.alarmArg;
  sqlite3_mutex_leave(mem0.mutex);
  xCallback(pArg, nowUsed, nByte);
  sqlite3_mutex_enter(mem0.mutex);
  mem0.alarmBusy = 0;
}

/*
** Do a memory allocation with statistics and alarms.  Assume the
** lock is already held.
*/
static int mallocWithAlarm(int n, void **pp){
  int nFull;
  void *p;
  assert( sqlite3_mutex_held(mem0.mutex) );
  nFull = sqlite3Config.m.xRoundup(n);
  sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
  if( mem0.alarmCallback!=0 ){
    int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
    if( nUsed+nFull >= mem0.alarmThreshold ){
      sqlite3MallocAlarm(nFull);
    }
  }
  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
    p = 0;
  }else{
    p = sqlite3Config.m.xMalloc(nFull);
    if( p==0 ){
      sqlite3MallocAlarm(nFull);
      p = malloc(nFull);
    }
  }
  if( p ) sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
  *pp = p;
  return nFull;
}

/*
** Allocate memory.  This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
void *sqlite3Malloc(int n){
  void *p;

  if( n<=0 ){
    p = 0;
  }else if( sqlite3Config.bMemstat ){

    sqlite3_mutex_enter(mem0.mutex);



















    mallocWithAlarm(n, &p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = sqlite3Config.m.xMalloc(n);
  }
  return p;
}

................................................................................

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
  /* Verify that no more than one scratch allocation per thread
  ** is outstanding at one time.  (This is only checked in the
  ** single-threaded case since checking in the multi-threaded case
  ** would be much more complicated.) */
  assert( scratchAllocOut==0 );

#endif

  if( sqlite3Config.szScratch<n ){
    goto scratch_overflow;
  }else{  
    sqlite3_mutex_enter(mem0.mutex);

    if( mem0.nScratchFree==0 ){

      sqlite3_mutex_leave(mem0.mutex);
      goto scratch_overflow;
    }else{
      int i;
      i = mem0.aScratchFree[--mem0.nScratchFree];
      sqlite3_mutex_leave(mem0.mutex);
      i *= sqlite3Config.szScratch;
      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
      p = (void*)&((char*)sqlite3Config.pScratch)[i];
    }
  }
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
  scratchAllocOut = p!=0;
#endif

  return p;

scratch_overflow:
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    n = mallocWithAlarm(n, &p);
    if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = sqlite3Config.m.xMalloc(n);
  }
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
  scratchAllocOut = p!=0;
#endif
  return p;    
}
void sqlite3ScratchFree(void *p){
  if( p ){

#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
    /* Verify that no more than one scratch allocation per thread
    ** is outstanding at one time.  (This is only checked in the
................................................................................
    ** single-threaded case since checking in the multi-threaded case
    ** would be much more complicated.) */
    assert( scratchAllocOut==1 );
    scratchAllocOut = 0;
#endif

    if( sqlite3Config.pScratch==0
           || p<sqlite3Config.pScratch
           || p>=(void*)mem0.aScratchFree ){
      if( sqlite3Config.bMemstat ){
        int iSize = sqlite3MallocSize(p);
        sqlite3_mutex_enter(mem0.mutex);
        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
        sqlite3Config.m.xFree(p);
        sqlite3_mutex_leave(mem0.mutex);
      }else{
        sqlite3Config.m.xFree(p);
      }
    }else{
      int i;


      i = p - sqlite3Config.pScratch;
      i /= sqlite3Config.szScratch;
      assert( i>=0 && i<sqlite3Config.nScratch );
      sqlite3_mutex_enter(mem0.mutex);
      assert( mem0.nScratchFree<sqlite3Config.nScratch );
      mem0.aScratchFree[mem0.nScratchFree++] = i;
      sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
      sqlite3_mutex_leave(mem0.mutex);
    }
  }
}

/*

** Allocate memory to be used by the page cache.  Make use of the
** memory buffer provided by SQLITE_CONFIG_PAGECACHE if there is one
** and that memory is of the right size and is not completely
** consumed.  Otherwise, failover to sqlite3Malloc().
*/
void *sqlite3PageMalloc(int n){
  void *p;
  assert( n>0 );
  assert( (n & (n-1))==0 );
  assert( n>=512 && n<=32768 );
  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
    return 0;
  }

  if( sqlite3Config.szPage<n ){
    goto page_overflow;
  }else{  
    sqlite3_mutex_enter(mem0.mutex);
    if( mem0.nPageFree==0 ){
      sqlite3_mutex_leave(mem0.mutex);
      goto page_overflow;
    }else{
      int i;
      i = mem0.aPageFree[--mem0.nPageFree];
      sqlite3_mutex_leave(mem0.mutex);
      i *= sqlite3Config.szPage;
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
      p = (void*)&((char*)sqlite3Config.pPage)[i];
    }
  }
  return p;

page_overflow:
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    n = mallocWithAlarm(n, &p);
    if( p ) sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = sqlite3Config.m.xMalloc(n);
  }
  return p;    
}
void sqlite3PageFree(void *p){

  if( p ){
    if( sqlite3Config.pPage==0
           || p<sqlite3Config.pPage
           || p>=(void*)mem0.aPageFree ){
      if( sqlite3Config.bMemstat ){
        int iSize = sqlite3MallocSize(p);
        sqlite3_mutex_enter(mem0.mutex);
        sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
        sqlite3Config.m.xFree(p);
        sqlite3_mutex_leave(mem0.mutex);
      }else{
        sqlite3Config.m.xFree(p);
      }
    }else{
      int i;
      i = p - sqlite3Config.pPage;
      i /= sqlite3Config.szPage;
      assert( i>=0 && i<sqlite3Config.nPage );
      sqlite3_mutex_enter(mem0.mutex);
      assert( mem0.nPageFree<sqlite3Config.nPage );
      mem0.aPageFree[mem0.nPageFree++] = i;
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
      sqlite3_mutex_leave(mem0.mutex);
    }
  }
}

/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
int sqlite3MallocSize(void *p){
  return sqlite3Config.m.xSize(p);
}
................................................................................
/*
** Free memory previously obtained from sqlite3Malloc().
*/
void sqlite3_free(void *p){
  if( p==0 ) return;
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
    sqlite3Config.m.xFree(p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    sqlite3Config.m.xFree(p);
  }
}

................................................................................
  if( nBytes<=0 ){
    sqlite3_free(pOld);
    return 0;
  }
  nOld = sqlite3MallocSize(pOld);
  if( sqlite3Config.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
    nNew = sqlite3Config.m.xRoundup(nBytes);
    if( nOld==nNew ){
      pNew = pOld;
    }else{
      if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= 
            mem0.alarmThreshold ){
        sqlite3MallocAlarm(nNew-nOld);
      }
      if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
        pNew = 0;
      }else{
        pNew = sqlite3Config.m.xRealloc(pOld, nNew);
        if( pNew==0 ){
          sqlite3MallocAlarm(nBytes);
          pNew = sqlite3Config.m.xRealloc(pOld, nNew);
        }
      }
      if( pNew ){
        sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);



      }
    }
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
  }
  return pNew;

Changes to src/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
....
5994
5995
5996
5997
5998
5999
6000

























































































6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.336 2008/06/18 18:57:42 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** </dd>
**
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd>This option specifies a static memory buffer that SQLite can use for
** scratch memory.  There are three arguments:  A pointer to the memory, the
** size of each scratch buffer (sz), and the number of buffers (N).  The sz
** argument must be a multiple of 16. The first
** argument should point to an allocation of at least (sz+1)*N bytes of memory.
** SQLite will use no more than one scratch buffer at once per thread, so
** N should be set to the expected maximum number of threads.  The sz 
** parameter should be 6 times the size of the largest database page size.
** Scratch buffers are used as part of the btree balance operation.  If
** The btree balancer needs additional memory beyond what is provided by
** scratch buffers or if no scratch buffer space is specified, then SQLite
** goes to [sqlite3_malloc()] to obtain the memory it needs.
................................................................................
#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES    3
#define SQLITE_TESTCTRL_FAULT_PENDING            4
#define SQLITE_TESTCTRL_PRNG_SAVE                5
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
#define SQLITE_TESTCTRL_PRNG_RESET               7
#define SQLITE_TESTCTRL_BITVEC_TEST              8



























































































/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif







|







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
....
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.337 2008/06/19 00:16:08 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
** </dd>
**
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd>This option specifies a static memory buffer that SQLite can use for
** scratch memory.  There are three arguments:  A pointer to the memory, the
** size of each scratch buffer (sz), and the number of buffers (N).  The sz
** argument must be a multiple of 16. The first
** argument should point to an allocation of at least (sz+4)*N bytes of memory.
** SQLite will use no more than one scratch buffer at once per thread, so
** N should be set to the expected maximum number of threads.  The sz 
** parameter should be 6 times the size of the largest database page size.
** Scratch buffers are used as part of the btree balance operation.  If
** The btree balancer needs additional memory beyond what is provided by
** scratch buffers or if no scratch buffer space is specified, then SQLite
** goes to [sqlite3_malloc()] to obtain the memory it needs.
................................................................................
#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES    3
#define SQLITE_TESTCTRL_FAULT_PENDING            4
#define SQLITE_TESTCTRL_PRNG_SAVE                5
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
#define SQLITE_TESTCTRL_PRNG_RESET               7
#define SQLITE_TESTCTRL_BITVEC_TEST              8

/*
** CAPI3REF: SQLite Runtime Status {F17200}
**
** This interface is used to retrieve run-time status information
** about the preformance of SQLite, and optionally to reset various
** highwater marks.  The first argument is an integer code for
** the specific parameter to measure.  Recognized integer codes
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].
** The current value of the parameter is returned into *pCurrent.
** The highest recorded value is returned in *pHighwater.  If the
** resetFlag is true, then the highest record value is reset after
** *pHighwater is written. Some parameters do not record the highest
** value.  For those parameters
** nothing is written into *pHighwater and the resetFlag is ignored.
** Other parameters record only the highwater mark and not the current
** value.  For these latter parameters nothing is written into *pCurrent.
**
** This routine returns SQLITE_OK on success and a non-zero
** [error code] on failure.
**
** This routine is threadsafe but is not atomic.  This routine can
** called while other threads are running the same or different SQLite
** interfaces.  However the values returned in *pCurrent and
** *pHighwater reflect the status of SQLite at different points in time
** and it is possible that another thread might change the parameter
** in between the times when *pCurrent and *pHighwater are written.
**
** This interface is experimental and is subject to change or
** removal in future releases of SQLite.
*/
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);

/*
** CAPI3REF: Status Parameters {F17250}
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
**
** <dl>
** <dt>SQLITE_STATUS_MEMORY_USED</dt>
** <dd>This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly.  The 
** figure includes calls made to [sqlite3_malloc()] by the application
** and internal memory usage by the SQLite library.  Scratch memory
** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
** this parameter.  The amount returned is the sum of the allocation
** sizes as are reported by the xSize method in [sqlite3_mem_methods].</dd>
**
** <dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
** page cache buffer configured using [SQLITE_CONFIG_PAGECACHE].  The
** value returned is in pages, not in bytes.</dd>
**
** <dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE]
** buffer and where forced to overflow to [sqlite3_malloc()].</dd>
**
** <dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>This parameter returns the number of allocations used out of the
** scratch allocation lookaside buffer configured using
** [SQLITE_CONFIG_SCRATCH].  The value returned is in allocations, not
** in bytes.  Since a single thread may only have one allocation
** outstanding at time, this parameter also reports the number of threads
** using scratch memory at the same time.</dd>
**
** <dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of scratch memory
** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH]
** buffer and where forced to overflow to [sqlite3_malloc()].</dd>
**
** <dt>SQLITE_STATUS_MALLOC_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
** internal equivalents).  The value of interest is return in the
** *pHighwater parameter to [sqlite3_status()].  The value written
** into the *pCurrent parameter is undefined.</dd>
** </dl>
**
** New status parameters may be added from time to time.
*/
#define SQLITE_STATUS_MEMORY_USED          0
#define SQLITE_STATUS_PAGECACHE_USED       1
#define SQLITE_STATUS_PAGECACHE_OVERFLOW   2
#define SQLITE_STATUS_SCRATCH_USED         3
#define SQLITE_STATUS_SCRATCH_OVERFLOW     4
#define SQLITE_STATUS_MALLOC_SIZE          5


/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE_OMIT_FLOATING_POINT
# undef double
#endif

#ifdef __cplusplus
}  /* End of the 'extern "C"' block */
#endif
#endif

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1806
1807
1808
1809
1810
1811
1812





1813
1814
1815
1816
1817
1818
1819
**    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.715 2008/06/18 18:57:42 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
void sqlite3MemSetDefault(void);

sqlite3_mutex_methods *sqlite3DefaultMutex(void);
sqlite3_mutex *sqlite3MutexAlloc(int);
int sqlite3MutexInit(void);
int sqlite3MutexEnd(void);






int sqlite3IsNaN(double);

char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
  void sqlite3DebugPrintf(const char*, ...);
#endif







|







 







>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
**    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.716 2008/06/19 00:16:08 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
void sqlite3MemSetDefault(void);

sqlite3_mutex_methods *sqlite3DefaultMutex(void);
sqlite3_mutex *sqlite3MutexAlloc(int);
int sqlite3MutexInit(void);
int sqlite3MutexEnd(void);

void sqlite3StatusReset(void);
int sqlite3StatusValue(int);
void sqlite3StatusAdd(int, int);
void sqlite3StatusSet(int, int);

int sqlite3IsNaN(double);

char *sqlite3MPrintf(sqlite3*,const char*, ...);
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
  void sqlite3DebugPrintf(const char*, ...);
#endif

Changes to src/test_malloc.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731


















































732
733
734
735
736
737
738
...
750
751
752
753
754
755
756

757
758
759
760
761
762
763
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.24 2008/06/18 18:12:04 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int sz, N, rc;
  Tcl_Obj *pResult;
  static char buf[20000];
  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[3], &N) ) return TCL_ERROR;
  if( sz<0 ){
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
  }else if( sz==0 ){
    int mx = sizeof(buf)/(sz+4);
    if( N>mx ) N = mx;
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
  }
  pResult = Tcl_NewObj();
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
................................................................................
  int sz, N, rc;
  Tcl_Obj *pResult;
  static char buf[100000];
  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[3], &N) ) return TCL_ERROR;
  if( sz<0 ){
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
  }else if( sz==0 ){
    int mx = sizeof(buf)/(sz+4);
    if( N>mx ) N = mx;
    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
  }
  pResult = Tcl_NewObj();
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
  Tcl_SetObjResult(interp, pResult);
  return TCL_OK;
}




















































/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_malloc_Init(Tcl_Interp *interp){
  static struct {
     char *zName;
................................................................................
     { "sqlite3_memdebug_fail",      test_memdebug_fail            },
     { "sqlite3_memdebug_pending",   test_memdebug_pending         },
     { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
     { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
     { "sqlite3_memdebug_log",       test_memdebug_log             },
     { "sqlite3_config_scratch",     test_config_scratch           },
     { "sqlite3_config_pagecache",   test_config_pagecache         },

  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  return TCL_OK;
}







|







 







|




|
|


|







 







|
|

|
|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
** $Id: test_malloc.c,v 1.25 2008/06/19 00:16:08 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

................................................................................
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int sz, N, rc;
  Tcl_Obj *pResult;
  static char buf[30000];
  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
  if( sz<0 ){
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
  }else{
    int mx = sizeof(buf)/(sz+4);
    if( N>mx ) N = mx;
    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
  }
  pResult = Tcl_NewObj();
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
................................................................................
  int sz, N, rc;
  Tcl_Obj *pResult;
  static char buf[100000];
  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
    return TCL_ERROR;
  }
  if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
  if( sz<0 ){
    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0);
  }else{
    int mx = sizeof(buf)/(sz+4);
    if( N>mx ) N = mx;
    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
  }
  pResult = Tcl_NewObj();
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
  Tcl_SetObjResult(interp, pResult);
  return TCL_OK;
}

/*
** Usage:    sqlite3_status  OPCODE  RESETFLAG
**
** Return a list of three elements which are the sqlite3_status() return
** code, the current value, and the high-water mark value.
*/
static int test_status(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int rc, iValue, mxValue;
  int i, op, resetFlag;
  const char *zOpName;
  static const struct {
    const char *zName;
    int op;
  } aOp[] = {
    { "SQLITE_STATUS_MEMORY_USED",         SQLITE_STATUS_MEMORY_USED         },
    { "SQLITE_STATUS_PAGECACHE_USED",      SQLITE_STATUS_PAGECACHE_USED      },
    { "SQLITE_STATUS_PAGECACHE_OVERFLOW",  SQLITE_STATUS_PAGECACHE_OVERFLOW  },
    { "SQLITE_STATUS_SCRATCH_USED",        SQLITE_STATUS_SCRATCH_USED        },
    { "SQLITE_STATUS_SCRATCH_OVERFLOW",    SQLITE_STATUS_SCRATCH_OVERFLOW    },
    { "SQLITE_STATUS_MALLOC_SIZE",         SQLITE_STATUS_MALLOC_SIZE         },
  };
  Tcl_Obj *pResult;
  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
    return TCL_ERROR;
  }
  zOpName = Tcl_GetString(objv[1]);
  for(i=0; i<ArraySize(aOp); i++){
    if( strcmp(aOp[i].zName, zOpName)==0 ){
      op = aOp[i].op;
      break;
    }
  }
  if( i>=ArraySize(aOp) ){
    if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
  }
  if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
  rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
  pResult = Tcl_NewObj();
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
  Tcl_SetObjResult(interp, pResult);
  return TCL_OK;
}

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_malloc_Init(Tcl_Interp *interp){
  static struct {
     char *zName;
................................................................................
     { "sqlite3_memdebug_fail",      test_memdebug_fail            },
     { "sqlite3_memdebug_pending",   test_memdebug_pending         },
     { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
     { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
     { "sqlite3_memdebug_log",       test_memdebug_log             },
     { "sqlite3_config_scratch",     test_config_scratch           },
     { "sqlite3_config_pagecache",   test_config_pagecache         },
     { "sqlite3_status",             test_status                   },
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  }
  return TCL_OK;
}

Added test/memsubsys1.test.

































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 2008 June 18
#
# 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 tests of the memory allocation subsystem
#
# $Id: memsubsys1.test,v 1.1 2008/06/19 00:16:08 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
# rebalance operations in the btree-layer and to require a large
# page cache), verifies correct results, then returns.
#
proc build_test_db {testname pragmas} {
  catch {db close}
  file delete -force test.db test.db-journal
  sqlite3 db test.db
  db eval $pragmas
  db eval {
    CREATE TABLE t1(x, y);
    CREATE TABLE t2(a, b);
    CREATE INDEX i1 ON t1(x,y);
    INSERT INTO t1 VALUES(1, 100);
    INSERT INTO t1 VALUES(2, 200);
  }
  for {set i 2} {$i<5000} {incr i $i} {
    db eval {INSERT INTO t2 SELECT * FROM t1}
    db eval {INSERT INTO t1 SELECT a+$i, a+b*100 FROM t2}
    db eval {DELETE FROM t2}
  }
  do_test $testname.1 {
    db eval {SELECT count(*) FROM t1}
  } 8192
  integrity_check $testname.2
}

# Test 1:  Both PAGECACHE and SCRATCH are shut down.
#
db close
sqlite3_shutdown
sqlite3_initialize
build_test_db memsubsys1-1 {PRAGMA page_size=1024}
do_test memsubsys1-1.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 0
do_test memsubsys1-1.4 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0
set max_pagecache [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
#show_memstats

# Test 2:  Activate PAGECACHE with 20 pages
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 1024 20
sqlite3_initialize
build_test_db memsubsys1-2 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-2.3 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
  expr {$pg_used*1024 + $pg_ovfl}
} $max_pagecache
do_test memsubsys1-2.4 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 20
do_test memsubsys1-2.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0

# Test 3:  Activate PAGECACHE with 20 pages but use the wrong page size
# so that PAGECACHE is not used.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 512 20
sqlite3_initialize
build_test_db memsubsys1-3.1 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-3.1.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 0
do_test memsubsys1-3.1.4 {
  set overflow [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} $max_pagecache
do_test memsubsys1-3.1.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0
db close
sqlite3_shutdown
sqlite3_config_pagecache 2048 20
sqlite3_initialize
build_test_db memsubsys1-3.2 {PRAGMA page_size=2048}
#show_memstats
do_test memsubsys1-3.2.3 {
  db eval {PRAGMA page_size}
} 2048
do_test memsubsys1-3.2.4 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 20
do_test memsubsys1-3.2.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0

# Test 4:  Activate both PAGECACHE and SCRATCH.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 1024 50
sqlite3_config_scratch 6000 2
sqlite3_initialize
build_test_db memsubsys1-4 {PRAGMA page_size=1024}
#show_memstats
do_test memsubsys1-4.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 50
do_test memsubsys1-4.4 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
  expr {$pg_used*1024 + $pg_ovfl}
} $max_pagecache
do_test memsubsys1-4.5 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq<4096}
} 1
do_test memsubsys1-4.6 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1

# Test 5:  Activate both PAGECACHE and SCRATCH.  But make the page size
# such that the SCRATCH allocations are too small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 6000 2
sqlite3_initialize
build_test_db memsubsys1-5 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-5.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 24
do_test memsubsys1-5.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq>4096}
} 1
do_test memsubsys1-5.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 0
do_test memsubsys1-5.6 {
  set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
  expr {$s_ovfl>6000}
} 1

# Test 6:  Activate both PAGECACHE and SCRATCH with a 4k page size.
# Make it so that SCRATCH is large enough
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
build_test_db memsubsys1-6 {PRAGMA page_size=4096}
#show_memstats
do_test memsubsys1-6.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
} 24
do_test memsubsys1-6.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
} 4096
do_test memsubsys1-6.5 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1
do_test memsubsys1-6.6 {
  set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
} 0

# Test 7:  Activate both PAGECACHE and SCRATCH with a 4k page size.
# Set cache_size small so that no PAGECACHE overflow occurs.  Verify
# that maximum allocation size is small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
breakpoint
build_test_db memsubsys1-7 {
  PRAGMA page_size=4096;
  PRAGMA cache_size=10;
  PRAGMA temp_cache_size=10;
}
#show_memstats
do_test memsubsys1-7.3 {
  set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
  expr {$pg_used<24}
} 1
do_test memsubsys1-7.4 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
} 0
do_test memsubsys1-7.5 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
  expr {$maxreq<2500}
} 1
do_test memsubsys1-7.6 {
  set s_used [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0] 2]
} 1
do_test memsubsys1-7.7 {
  set s_ovfl [lindex [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0] 2]
} 0


finish_test

Changes to test/tester.tcl.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
329
330
331
332
333
334
335

336
337
338
339
340
341
342
...
354
355
356
357
358
359
360






















361
362
363
364
365
366
367
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.126 2008/06/07 05:19:38 danielk1977 Exp $

#
# What for user input before continuing.  This gives an opportunity
# to connect profiling tools to the process.
#
for {set i 0} {$i<[llength $argv]} {incr i} {
  if {[regexp {^-+pause$} [lindex $argv $i] all value]} {
................................................................................
    }
  } else {
    puts "All memory allocations freed - no leaks"
    ifcapable memdebug||mem5 {
      sqlite3_memdebug_dump ./memusage.txt
    }
  }

  puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
  puts "Current memory usage: [sqlite3_memory_highwater] bytes"
  if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
    puts "Number of malloc()  : [sqlite3_memdebug_malloc_count] calls"
  }
  if {[info exists ::tester_do_malloctrace]} {
    puts "Writing mallocs.sql..."
................................................................................
    file delete -force $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    file delete -force $f
  }
  exit [expr {$nErr>0}]
}























# A procedure to execute SQL
#
proc execsql {sql {db db}} {
  # puts "SQL = $sql"
  uplevel [list $db eval $sql]
}







|







 







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.127 2008/06/19 00:16:08 drh Exp $

#
# What for user input before continuing.  This gives an opportunity
# to connect profiling tools to the process.
#
for {set i 0} {$i<[llength $argv]} {incr i} {
  if {[regexp {^-+pause$} [lindex $argv $i] all value]} {
................................................................................
    }
  } else {
    puts "All memory allocations freed - no leaks"
    ifcapable memdebug||mem5 {
      sqlite3_memdebug_dump ./memusage.txt
    }
  }
  show_memstats
  puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
  puts "Current memory usage: [sqlite3_memory_highwater] bytes"
  if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
    puts "Number of malloc()  : [sqlite3_memdebug_malloc_count] calls"
  }
  if {[info exists ::tester_do_malloctrace]} {
    puts "Writing mallocs.sql..."
................................................................................
    file delete -force $f
  }
  foreach f [glob -nocomplain test.db-mj*] {
    file delete -force $f
  }
  exit [expr {$nErr>0}]
}

# Display memory statistics for analysis and debugging purposes.
#
proc show_memstats {} {
  set x [sqlite3_status SQLITE_STATUS_MEMORY_USED 0]
  set val [format {now %10d  max %10d} [lindex $x 1] [lindex $x 2]]
  puts "Memory used:          $val"
  set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0]
  set val [format {now %10d  max %10d} [lindex $x 1] [lindex $x 2]]
  puts "Page-cache used:      $val"
  set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
  set val [format {now %10d  max %10d} [lindex $x 1] [lindex $x 2]]
  puts "Page-cache overflow:  $val"
  set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
  set val [format {now %10d  max %10d} [lindex $x 1] [lindex $x 2]]
  puts "Scratch memory used:  $val"
  set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
  set val [format {now %10d  max %10d} [lindex $x 1] [lindex $x 2]]
  puts "Scratch overflow:     $val"
  set x [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
  puts "Maximum alloc size:   [lindex $x 2]"
}

# A procedure to execute SQL
#
proc execsql {sql {db db}} {
  # puts "SQL = $sql"
  uplevel [list $db eval $sql]
}

Changes to tool/mksqlite3c.tcl.

200
201
202
203
204
205
206

207
208
209
210
211
212
213
# used subroutines first in order to help the compiler find
# inlining opportunities.
#
foreach file {
   sqliteInt.h

   global.c

   date.c
   os.c

   fault.c
   mem1.c
   mem2.c
   mutex.c







>







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# used subroutines first in order to help the compiler find
# inlining opportunities.
#
foreach file {
   sqliteInt.h

   global.c
   status.c
   date.c
   os.c

   fault.c
   mem1.c
   mem2.c
   mutex.c