/ Check-in [2091d9a5]
Login

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

Overview
Comment:Fix soft-heap-limit related test suite failures. (CVS 5582)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:2091d9a5260b1d7e27ff5ca93e60dae1e3b12081
User & Date: danielk1977 2008-08-21 15:54:01
Context
2008-08-21
18:49
Initialize the global built-in function table at start-time instead of at compile-time. This is less prone to malfunction when compile-time parameters very. (CVS 5583) check-in: ef6936e5 user: drh tags: trunk
15:54
Fix soft-heap-limit related test suite failures. (CVS 5582) check-in: 2091d9a5 user: danielk1977 tags: trunk
15:13
Increase the version number in preparation for the next release. (CVS 5581) check-in: d68dad73 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pcache.c.

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



100
101
102
103
104
105
106
...
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
...
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
...
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
...
562
563
564
565
566
567
568

569
570
571
572
573
574
575
...
854
855
856
857
858
859
860

861
862
863
864
865
866
867
....
1147
1148
1149
1150
1151
1152
1153


1154
1155
1156
1157
1158
1159
1160

1161
1162
1163
1164
1165
1166
1167

1168
1169

1170
1171
1172
1173
1174
1175
1176
**    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 implements that page cache.
**
** @(#) $Id: pcache.c,v 1.5 2008/08/21 12:32:12 drh Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
*/
struct PCache {
................................................................................
** from within a call to sqlite3PcacheFetch() on the same pager. A call
** to sqlite3PcacheLock() may block if such an xStress() call is currently 
** underway.
**
** Before the xStress callback of a pager-cache (PCache) is invoked, the
** SQLITE_MUTEX_STATIC_MEM2 mutex is obtained and the SQLITE_MUTEX_STATIC_LRU 
** mutex released (in that order) before making the call.



*/

#define pcacheEnterGlobal() sqlite3_mutex_enter(pcache.mutex_lru)
#define pcacheExitGlobal()  sqlite3_mutex_leave(pcache.mutex_lru)

/*
** Increment the reference count on both page p and its cache by n.
................................................................................
}

/*
** Allocate a page cache line.  Look in the page cache memory pool first
** and use an element from it first if available.  If nothing is available
** in the page cache memory pool, go to the general purpose memory allocator.
*/
void *pcacheMalloc(int sz){
  assert( sqlite3_mutex_held(pcache.mutex_lru) );
  if( sz<=pcache.szSlot && pcache.pFree ){
    PgFreeslot *p = pcache.pFree;
    pcache.pFree = p->pNext;
    sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
    return (void*)p;
  }else{
    void *p;









    pcacheExitGlobal();

    p = sqlite3Malloc(sz);

    pcacheEnterGlobal();

    if( p ){
      sz = sqlite3MallocSize(p);
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
    }
    return p;
  }
}
void *sqlite3PageMalloc(sz){
  void *p;
  pcacheEnterGlobal();
  p = pcacheMalloc(sz);
  pcacheExitGlobal();
  return p;
}

/*
** Release a pager memory allocation
*/
................................................................................
  pcacheFree(p);
  pcacheExitGlobal();
}

/*
** Allocate a new page.
*/
static PgHdr *pcachePageAlloc(int szPage, int szExtra, int bPurgeable){
  PgHdr *p;
  int sz = sizeof(*p) + szPage + szExtra;
  assert( sqlite3_mutex_held(pcache.mutex_lru) );
  p = pcacheMalloc( sz );
  if( p==0 ) return 0;
  memset(p, 0, sizeof(PgHdr));
  p->pData = (void*)&p[1];
  p->pExtra = (void*)&((char*)p->pData)[szPage];

  pcache.nPage++;
  if( bPurgeable ){
    pcache.nPurgeable++;
  }

  return p;
}

/*
................................................................................

  if( p && (p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra) ){
    pcachePageFree(p);
    p = 0;
  }

  if( !p ){
    /* Allocate a new page object. */
    p = pcachePageAlloc(szPage, szExtra, bPurg);
  }

  pcacheExitGlobal();
  return p;
}

/*************************************************** General Interfaces ******
................................................................................
  if( bPurgeable ){
    pcacheEnterGlobal();
    pcache.mxPagePurgeable += p->nMax;
    pcacheExitGlobal();
  }

  /* Add the new pager-cache to the list of caches starting at pcache.pAll */

  sqlite3_mutex_enter(pcache.mutex_mem2);
  p->pNextAll = pcache.pAll;
  if( pcache.pAll ){
    pcache.pAll->pPrevAll = p;
  }
  p->pPrevAll = 0;
  pcache.pAll = p;
................................................................................
  sqlite3_free(pCache->apHash);
  pcacheExitGlobal();

  /* Now remove the pager-cache structure itself from the list of
  ** all such structures headed by pcache.pAll. This required the
  ** MUTEX_STATIC_MEM2 mutex.
  */

  sqlite3_mutex_enter(pcache.mutex_mem2);
  assert(pCache==pcache.pAll || pCache->pPrevAll);
  assert(pCache->pNextAll==0 || pCache->pNextAll->pPrevAll==pCache);
  assert(pCache->pPrevAll==0 || pCache->pPrevAll->pNextAll==pCache);
  if( pCache->pPrevAll ){
    pCache->pPrevAll->pNextAll = pCache->pNextAll;
  }else{
................................................................................
  pCache->nMax = mxPage;
}

/*
** Lock a pager-cache.
*/
void sqlite3PcacheLock(PCache *pCache){


  pCache->iInUseDB++;
  if( pCache->iInUseMM && pCache->iInUseDB==1 ){
    pCache->iInUseDB = 0;
    sqlite3_mutex_enter(pcache.mutex_mem2);
    assert( pCache->iInUseMM==0 && pCache->iInUseDB==0 );
    pCache->iInUseDB = 1;
    sqlite3_mutex_leave(pcache.mutex_mem2);

  }
}

/*
** Unlock a pager-cache.
*/
void sqlite3PcacheUnlock(PCache *pCache){

  pCache->iInUseDB--;
  assert( pCache->iInUseDB>=0 );

}

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** This function is called to free superfluous dynamically allocated memory
** held by the pager system. Memory in use by any SQLite pager allocated
** by the current thread may be sqlite3_free()ed.







|







 







>
>
>







 







|









>
>
>
>
>
>
>
>
>

>

>

>










|







 







|

|

|



|
<

|







 







<
|







 







>







 







>







 







>
>
|
|
|
|
|
|
|
>







>
|
|
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
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
...
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
...
511
512
513
514
515
516
517

518
519
520
521
522
523
524
525
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
....
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
**    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 implements that page cache.
**
** @(#) $Id: pcache.c,v 1.6 2008/08/21 15:54:01 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
*/
struct PCache {
................................................................................
** from within a call to sqlite3PcacheFetch() on the same pager. A call
** to sqlite3PcacheLock() may block if such an xStress() call is currently 
** underway.
**
** Before the xStress callback of a pager-cache (PCache) is invoked, the
** SQLITE_MUTEX_STATIC_MEM2 mutex is obtained and the SQLITE_MUTEX_STATIC_LRU 
** mutex released (in that order) before making the call.
**
** Deadlock within the module is avoided by never blocking on the MEM2 
** mutex while the LRU mutex is held.
*/

#define pcacheEnterGlobal() sqlite3_mutex_enter(pcache.mutex_lru)
#define pcacheExitGlobal()  sqlite3_mutex_leave(pcache.mutex_lru)

/*
** Increment the reference count on both page p and its cache by n.
................................................................................
}

/*
** Allocate a page cache line.  Look in the page cache memory pool first
** and use an element from it first if available.  If nothing is available
** in the page cache memory pool, go to the general purpose memory allocator.
*/
void *pcacheMalloc(int sz, PCache *pCache){
  assert( sqlite3_mutex_held(pcache.mutex_lru) );
  if( sz<=pcache.szSlot && pcache.pFree ){
    PgFreeslot *p = pcache.pFree;
    pcache.pFree = p->pNext;
    sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
    return (void*)p;
  }else{
    void *p;

    /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
    ** global pcache mutex and unlock the pager-cache object pCache. This is 
    ** so that if the attempt to allocate a new buffer causes the the 
    ** configured soft-heap-limit to be breached, it will be possible to
    ** reclaim memory from this pager-cache. Because sqlite3PcacheLock() 
    ** might block on the MEM2 mutex, it has to be called before re-entering
    ** the global LRU mutex.
    */
    pcacheExitGlobal();
    sqlite3PcacheUnlock(pCache);
    p = sqlite3Malloc(sz);
    sqlite3PcacheLock(pCache);
    pcacheEnterGlobal();

    if( p ){
      sz = sqlite3MallocSize(p);
      sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
    }
    return p;
  }
}
void *sqlite3PageMalloc(sz){
  void *p;
  pcacheEnterGlobal();
  p = pcacheMalloc(sz, 0);
  pcacheExitGlobal();
  return p;
}

/*
** Release a pager memory allocation
*/
................................................................................
  pcacheFree(p);
  pcacheExitGlobal();
}

/*
** Allocate a new page.
*/
static PgHdr *pcachePageAlloc(PCache *pCache){
  PgHdr *p;
  int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
  assert( sqlite3_mutex_held(pcache.mutex_lru) );
  p = pcacheMalloc(sz, pCache);
  if( p==0 ) return 0;
  memset(p, 0, sizeof(PgHdr));
  p->pData = (void*)&p[1];
  p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];

  pcache.nPage++;
  if( pCache->bPurgeable ){
    pcache.nPurgeable++;
  }

  return p;
}

/*
................................................................................

  if( p && (p->pCache->szPage!=szPage || p->pCache->szExtra!=szExtra) ){
    pcachePageFree(p);
    p = 0;
  }

  if( !p ){

    p = pcachePageAlloc(pCache);
  }

  pcacheExitGlobal();
  return p;
}

/*************************************************** General Interfaces ******
................................................................................
  if( bPurgeable ){
    pcacheEnterGlobal();
    pcache.mxPagePurgeable += p->nMax;
    pcacheExitGlobal();
  }

  /* Add the new pager-cache to the list of caches starting at pcache.pAll */
  assert( sqlite3_mutex_notheld(pcache.mutex_lru) );
  sqlite3_mutex_enter(pcache.mutex_mem2);
  p->pNextAll = pcache.pAll;
  if( pcache.pAll ){
    pcache.pAll->pPrevAll = p;
  }
  p->pPrevAll = 0;
  pcache.pAll = p;
................................................................................
  sqlite3_free(pCache->apHash);
  pcacheExitGlobal();

  /* Now remove the pager-cache structure itself from the list of
  ** all such structures headed by pcache.pAll. This required the
  ** MUTEX_STATIC_MEM2 mutex.
  */
  assert( sqlite3_mutex_notheld(pcache.mutex_lru) );
  sqlite3_mutex_enter(pcache.mutex_mem2);
  assert(pCache==pcache.pAll || pCache->pPrevAll);
  assert(pCache->pNextAll==0 || pCache->pNextAll->pPrevAll==pCache);
  assert(pCache->pPrevAll==0 || pCache->pPrevAll->pNextAll==pCache);
  if( pCache->pPrevAll ){
    pCache->pPrevAll->pNextAll = pCache->pNextAll;
  }else{
................................................................................
  pCache->nMax = mxPage;
}

/*
** Lock a pager-cache.
*/
void sqlite3PcacheLock(PCache *pCache){
  if( pCache ){
    assert( sqlite3_mutex_notheld(pcache.mutex_lru) );
    pCache->iInUseDB++;
    if( pCache->iInUseMM && pCache->iInUseDB==1 ){
      pCache->iInUseDB = 0;
      sqlite3_mutex_enter(pcache.mutex_mem2);
      assert( pCache->iInUseMM==0 && pCache->iInUseDB==0 );
      pCache->iInUseDB = 1;
      sqlite3_mutex_leave(pcache.mutex_mem2);
    }
  }
}

/*
** Unlock a pager-cache.
*/
void sqlite3PcacheUnlock(PCache *pCache){
  if( pCache ){
    pCache->iInUseDB--;
    assert( pCache->iInUseDB>=0 );
  }
}

#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** This function is called to free superfluous dynamically allocated memory
** held by the pager system. Memory in use by any SQLite pager allocated
** by the current thread may be sqlite3_free()ed.

Changes to test/malloc5.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
...
292
293
294
295
296
297
298



299
300
301
302
303
304
305
...
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
...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains test cases focused on the two memory-management APIs, 
# sqlite3_soft_heap_limit() and sqlite3_release_memory().
#
# $Id: malloc5.test,v 1.18 2008/02/18 22:24:58 drh Exp $

#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
#
#---------------------------------------------------------------------------


................................................................................
  execsql {COMMIT;}
  set nMaxBytes [sqlite3_memory_highwater 1]
  puts -nonewline " (Highwater mark: $nMaxBytes) "
  expr $nMaxBytes > 1000000
} {1}
do_test malloc5-4.2 {
  sqlite3_release_memory
  sqlite3_soft_heap_limit 100000
  sqlite3_memory_highwater 1
  execsql {BEGIN;}
  for {set i 0} {$i < 10000} {incr i} {
    execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');"
  }
  execsql {COMMIT;}
  set nMaxBytes [sqlite3_memory_highwater 1]
................................................................................
  # used to store cached page data are both small and transient.
  #
  # Summary: the actual high-water mark for memory usage may be slightly 
  # higher than the soft-heap-limit. The specific allocations that cause
  # the problem are the calls to sqlite3_malloc() inserted into selected
  # sqlite3OsXXX() functions in test builds.
  #
  expr $nMaxBytes <= 100100
} {1}
do_test malloc5-4.3 {
  # Check that the content of table abc is at least roughly as expected.
  execsql {
    SELECT count(*), sum(a), sum(b) FROM abc;
  }
} [list 20000 [expr int(20000.0 * 4999.5)] [expr int(20000.0 * 4999.5)]]
................................................................................
# This block of test-cases (malloc5-6.1.*) prepares two database files
# for the subsequent tests.
do_test malloc5-6.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;
    PRAGMA default_cache_size=10;



    BEGIN;
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    INSERT INTO abc VALUES(randstr(50,50), randstr(75,75), randstr(100,100));
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
................................................................................
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}

do_test malloc5-6.2.1 {
  execsql { SELECT * FROM abc } db2
  execsql {SELECT * FROM abc} db
  list [nPage db] [nPage db2]
} {10 10}

do_test malloc5-6.2.2 {
  # If we now try to reclaim some memory, it should come from the db2 cache.
  sqlite3_release_memory 3000
  list [nPage db] [nPage db2]
} {10 7}
do_test malloc5-6.2.3 {
  # Access the db2 cache again, so that all the db2 pages have been used
  # more recently than all the db pages. Then try to reclaim 3000 bytes.
  # This time, 3 pages should be pulled from the db cache.
  execsql { SELECT * FROM abc } db2
  sqlite3_release_memory 3000
  list [nPage db] [nPage db2]
} {7 10}


do_test malloc5-6.3.1 {
  # Now open a transaction and update 2 pages in the db2 cache. Then
  # do a SELECT on the db cache so that all the db pages are more recently
  # used than the db2 pages. When we try to free memory, SQLite should
  # free the non-dirty db2 pages, then the db pages, then finally use
  # sync() to free up the dirty db2 pages. The only page that cannot be
................................................................................
  # btree layer holds a reference to page 1 in the db2 cache.
  execsql {
    BEGIN;
    UPDATE abc SET c = randstr(100,100) 
    WHERE rowid = 1 OR rowid = (SELECT max(rowid) FROM abc);
  } db2
  execsql { SELECT * FROM abc } db
  list [nPage db] [nPage db2]
} {10 10}
do_test malloc5-6.3.2 {
  # Try to release 7700 bytes. This should release all the 
  # non-dirty pages held by db2.
  sqlite3_release_memory [expr 7*1100]
  list [nPage db] [nPage db2]
} {10 3}
do_test malloc5-6.3.3 {







|







 







|







 







|







 







>
>
>







 







|
|
>



|
|






|
|
<







 







|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
...
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
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
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file contains test cases focused on the two memory-management APIs, 
# sqlite3_soft_heap_limit() and sqlite3_release_memory().
#
# $Id: malloc5.test,v 1.19 2008/08/21 15:54:01 danielk1977 Exp $

#---------------------------------------------------------------------------
# NOTES ON EXPECTED BEHAVIOUR
#
#---------------------------------------------------------------------------


................................................................................
  execsql {COMMIT;}
  set nMaxBytes [sqlite3_memory_highwater 1]
  puts -nonewline " (Highwater mark: $nMaxBytes) "
  expr $nMaxBytes > 1000000
} {1}
do_test malloc5-4.2 {
  sqlite3_release_memory
  sqlite3_soft_heap_limit 110000
  sqlite3_memory_highwater 1
  execsql {BEGIN;}
  for {set i 0} {$i < 10000} {incr i} {
    execsql "INSERT INTO abc VALUES($i, $i, '[string repeat X 100]');"
  }
  execsql {COMMIT;}
  set nMaxBytes [sqlite3_memory_highwater 1]
................................................................................
  # used to store cached page data are both small and transient.
  #
  # Summary: the actual high-water mark for memory usage may be slightly 
  # higher than the soft-heap-limit. The specific allocations that cause
  # the problem are the calls to sqlite3_malloc() inserted into selected
  # sqlite3OsXXX() functions in test builds.
  #
  expr $nMaxBytes <= 110100
} {1}
do_test malloc5-4.3 {
  # Check that the content of table abc is at least roughly as expected.
  execsql {
    SELECT count(*), sum(a), sum(b) FROM abc;
  }
} [list 20000 [expr int(20000.0 * 4999.5)] [expr int(20000.0 * 4999.5)]]
................................................................................
# This block of test-cases (malloc5-6.1.*) prepares two database files
# for the subsequent tests.
do_test malloc5-6.1.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA page_size=1024;
    PRAGMA default_cache_size=10;
  }
  execsql {
    PRAGMA temp_store = memory;
    BEGIN;
    CREATE TABLE abc(a PRIMARY KEY, b, c);
    INSERT INTO abc VALUES(randstr(50,50), randstr(75,75), randstr(100,100));
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
    INSERT INTO abc 
        SELECT randstr(50,50), randstr(75,75), randstr(100,100) FROM abc;
................................................................................
do_test malloc5-6.1.2 {
  list [execsql {PRAGMA cache_size}] [execsql {PRAGMA cache_size} db2]
} {10 10}

do_test malloc5-6.2.1 {
  execsql { SELECT * FROM abc } db2
  execsql {SELECT * FROM abc} db
  expr [nPage db] + [nPage db2]
} {20}

do_test malloc5-6.2.2 {
  # If we now try to reclaim some memory, it should come from the db2 cache.
  sqlite3_release_memory 3000
  expr [nPage db] + [nPage db2]
} {17}
do_test malloc5-6.2.3 {
  # Access the db2 cache again, so that all the db2 pages have been used
  # more recently than all the db pages. Then try to reclaim 3000 bytes.
  # This time, 3 pages should be pulled from the db cache.
  execsql { SELECT * FROM abc } db2
  sqlite3_release_memory 3000
  expr [nPage db] + [nPage db2]
} {17}


do_test malloc5-6.3.1 {
  # Now open a transaction and update 2 pages in the db2 cache. Then
  # do a SELECT on the db cache so that all the db pages are more recently
  # used than the db2 pages. When we try to free memory, SQLite should
  # free the non-dirty db2 pages, then the db pages, then finally use
  # sync() to free up the dirty db2 pages. The only page that cannot be
................................................................................
  # btree layer holds a reference to page 1 in the db2 cache.
  execsql {
    BEGIN;
    UPDATE abc SET c = randstr(100,100) 
    WHERE rowid = 1 OR rowid = (SELECT max(rowid) FROM abc);
  } db2
  execsql { SELECT * FROM abc } db
  expr [nPage db] + [nPage db2]
} {20}
do_test malloc5-6.3.2 {
  # Try to release 7700 bytes. This should release all the 
  # non-dirty pages held by db2.
  sqlite3_release_memory [expr 7*1100]
  list [nPage db] [nPage db2]
} {10 3}
do_test malloc5-6.3.3 {

Changes to test/permutations.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
137
138
139
140
141
142
143



144
145
146
147
148
149
150
#
#    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: permutations.test,v 1.20 2008/08/01 18:47:02 drh Exp $

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

# Argument processing.
#
set ::testmode [lindex $argv 0]
................................................................................
#############################################################################
# Start of tests

# Run some tests using pre-allocated page and scratch blocks.
#
run_tests "memsubsys1" -description {
  Tests using pre-allocated page and scratch blocks



} -initialize {
  catch {db close}
  sqlite3_shutdown
  sqlite3_config_pagecache 4096 24
  sqlite3_config_scratch 25000 1
  sqlite3_initialize
} -shutdown {







|







 







>
>
>







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#
#    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: permutations.test,v 1.21 2008/08/21 15:54:01 danielk1977 Exp $

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

# Argument processing.
#
set ::testmode [lindex $argv 0]
................................................................................
#############################################################################
# Start of tests

# Run some tests using pre-allocated page and scratch blocks.
#
run_tests "memsubsys1" -description {
  Tests using pre-allocated page and scratch blocks
} -exclude {
  ioerr5.test
  malloc5.test
} -initialize {
  catch {db close}
  sqlite3_shutdown
  sqlite3_config_pagecache 4096 24
  sqlite3_config_scratch 25000 1
  sqlite3_initialize
} -shutdown {