SQLite

Check-in [697fe7a316]
Login

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

Overview
Comment:Revise the initialization and shutdown logic so that it no longer keeps a recursive mutex allocated for the whole interval but instead releases the mutex as soon as possible. Do not reset status values upon initialization. (CVS 5559)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 697fe7a3167c22a3232ce154e9d47cf75af613c4
User & Date: drh 2008-08-12 15:21:12.000
Context
2008-08-12
15:48
Make sure the lookaside test script saturates the lookaside buffer even when SQLITE_DEBUG is off. Ticket #3289 (CVS 5560) (check-in: d6aacc5dc7 user: drh tags: trunk)
15:21
Revise the initialization and shutdown logic so that it no longer keeps a recursive mutex allocated for the whole interval but instead releases the mutex as soon as possible. Do not reset status values upon initialization. (CVS 5559) (check-in: 697fe7a316 user: drh tags: trunk)
15:04
Fix further warnings/compilation errors in test code. (CVS 5558) (check-in: 42247b917a user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.487 2008/08/08 14:33:13 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.488 2008/08/12 15:21:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

#ifdef SQLITE_ENABLE_FTS3
# include "fts3.h"
#endif
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
*/
char *sqlite3_temp_directory = 0;

/*
** Initialize SQLite.  
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystesms prior to doing any serious work with
** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().  
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.



















*/
int sqlite3_initialize(void){
  static int inProgress = 0;

  int rc;

  /* If SQLite is already initialized, this call is a no-op. */




  if( sqlite3Config.isInit ) return SQLITE_OK;

  /* Make sure the mutex system is initialized. */







  rc = sqlite3MutexInit();

  if( rc==SQLITE_OK ){

    /* Initialize the malloc() system and the recursive pInitMutex mutex.
    ** This operation is protected by the STATIC_MASTER mutex.



    */
    sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
    sqlite3_mutex_enter(pMaster);
    if( !sqlite3Config.isMallocInit ){
      rc = sqlite3MallocInit();
    }
    if( rc==SQLITE_OK ){
      sqlite3Config.isMallocInit = 1;
      if( !sqlite3Config.pInitMutex ){
        sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
        if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
          rc = SQLITE_NOMEM;
        }
      }

    }
    sqlite3_mutex_leave(pMaster);





    if( rc!=SQLITE_OK ){
      return rc;
    }

    /* Enter the recursive pInitMutex mutex. After doing so, if the
    ** sqlite3Config.isInit flag is true, then some other thread has
    ** finished doing the initialization. If the inProgress flag is
    ** true, then this function is being called recursively from within

    ** the sqlite3_os_init() call below. In either case, exit early.

    */
    sqlite3_mutex_enter(sqlite3Config.pInitMutex);
    if( sqlite3Config.isInit || inProgress ){
      sqlite3_mutex_leave(sqlite3Config.pInitMutex);
      return SQLITE_OK;
    }
    sqlite3StatusReset();
    inProgress = 1;
    rc = sqlite3_os_init();
    inProgress = 0;
    sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);

    sqlite3_mutex_leave(sqlite3Config.pInitMutex);
  }











  /* Check NaN support. */





#ifndef NDEBUG
  /* This section of code's only "output" is via assert() statements. */
  if ( rc==SQLITE_OK ){
    u64 x = (((u64)1)<<63)-1;
    double y;
    assert(sizeof(x)==8);
    assert(sizeof(x)==sizeof(y));







|






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


|
>
|

|
>
>
>
>


|
>
>
>
>
>
>
>

|
<

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

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




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







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
*/
char *sqlite3_temp_directory = 0;

/*
** Initialize SQLite.  
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystems prior to doing any serious work with
** SQLite.  But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().  
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
**
** The first thread to call this routine runs the initialization to
** completion.  If subsequent threads call this routine before the first
** thread has finished the initialization process, then the subsequent
** threads must block until the first thread finishes with the initialization.
**
** The first thread might call this routine recursively.  Recursive
** calls to this routine should not block, of course.  Otherwise the
** initialization process would never complete.
**
** Let X be the first thread to enter this routine.  Let Y be some other
** thread.  Then while the initial invocation of this routine by X is
** incomplete, it is required that:
**
**    *  Calls to this routine from Y must block until the outer-most
**       call by X completes.
**
**    *  Recursive calls to this routine from thread X return immediately
**       without blocking.
*/
int sqlite3_initialize(void){
  static int inProgress = 0;        /* Prevent recursion */
  sqlite3_mutex *pMaster;           /* The main static mutex */
  int rc;                           /* Result code */

  /* If SQLite is already completely initialized, then this call
  ** to sqlite3_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end
  ** of this routine.
  */
  if( sqlite3Config.isInit ) return SQLITE_OK;

  /* Make sure the mutex subsystem is initialized.  If unable to 
  ** initialize the mutex subsystem, return early with the error.
  ** If the system is so sick that we are unable to allocate a mutex,
  ** there is not much SQLite is going to be able to do.
  **
  ** The mutex subsystem must take care of serializing its own
  ** initialization.
  */
  rc = sqlite3MutexInit();
  if( rc ) return rc;


  /* Initialize the malloc() system and the recursive pInitMutex mutex.
  ** This operation is protected by the STATIC_MASTER mutex.  Note that
  ** MutexAlloc() is called for a static mutex prior to initializing the
  ** malloc subsystem - this implies that the allocation of a static
  ** mutex must not require support from the malloc subsystem.
  */
  pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(pMaster);
  if( !sqlite3Config.isMallocInit ){
    rc = sqlite3MallocInit();
  }
  if( rc==SQLITE_OK ){
    sqlite3Config.isMallocInit = 1;
    if( !sqlite3Config.pInitMutex ){
      sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
      if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
        rc = SQLITE_NOMEM;
      }
    }
    sqlite3Config.nRefInitMutex++;
  }
  sqlite3_mutex_leave(pMaster);

  /* If unable to initialize the malloc subsystem, then return early.
  ** There is little hope of getting SQLite to run if the malloc
  ** subsystem cannot be initialized.
  */
  if( rc!=SQLITE_OK ){
    return rc;
  }



  /* Do the rest of the initialization under the recursive mutex so
  ** that we will be able to handle recursive calls into
  ** sqlite3_initialize().  The recursive calls normally come through
  ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
  ** recursive calls might also be possible.
  */
  sqlite3_mutex_enter(sqlite3Config.pInitMutex);
  if( sqlite3Config.isInit==0 && inProgress==0 ){




    inProgress = 1;
    rc = sqlite3_os_init();
    inProgress = 0;
    sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
  }
  sqlite3_mutex_leave(sqlite3Config.pInitMutex);

  /* Go back under the static mutex and clean up the recursive
  ** mutex to prevent a resource leak.
  */
  sqlite3_mutex_enter(pMaster);
  sqlite3Config.nRefInitMutex--;
  if( sqlite3Config.nRefInitMutex<=0 ){
    assert( sqlite3Config.nRefInitMutex==0 );
    sqlite3_mutex_free(sqlite3Config.pInitMutex);
    sqlite3Config.pInitMutex = 0;
  }
  sqlite3_mutex_leave(pMaster);

  /* The following is just a sanity check to make sure SQLite has
  ** been compiled correctly.  It is important to run this code, but
  ** we don't want to run it too often and soak up CPU cycles for no
  ** reason.  So we run it once during initialization.
  */
#ifndef NDEBUG
  /* This section of code's only "output" is via assert() statements. */
  if ( rc==SQLITE_OK ){
    u64 x = (((u64)1)<<63)-1;
    double y;
    assert(sizeof(x)==8);
    assert(sizeof(x)==sizeof(y));
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
** Undo the effects of sqlite3_initialize().  Must not be called while
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread.  This
** routine is not threadsafe.  Not by a long shot.
*/
int sqlite3_shutdown(void){
  sqlite3_mutex_free(sqlite3Config.pInitMutex);
  sqlite3Config.pInitMutex = 0;
  sqlite3Config.isMallocInit = 0;
  if( sqlite3Config.isInit ){
    sqlite3_os_end();
  }
  if( sqlite3Config.m.xShutdown ){
    sqlite3MallocEnd();
  }







<
<







188
189
190
191
192
193
194


195
196
197
198
199
200
201
/*
** Undo the effects of sqlite3_initialize().  Must not be called while
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread.  This
** routine is not threadsafe.  Not by a long shot.
*/
int sqlite3_shutdown(void){


  sqlite3Config.isMallocInit = 0;
  if( sqlite3Config.isInit ){
    sqlite3_os_end();
  }
  if( sqlite3Config.m.xShutdown ){
    sqlite3MallocEnd();
  }
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.752 2008/08/04 20:13:27 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.753 2008/08/12 15:21:12 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
1827
1828
1829
1830
1831
1832
1833

1834
1835
1836
1837
1838
1839
1840
  int nScratch;                     /* Number of scratch buffers */
  void *pPage;                      /* Page cache memory */
  int szPage;                       /* Size of each page in pPage[] */
  int nPage;                        /* Number of pages in pPage[] */
  int isInit;                       /* True after initialization has finished */
  int isMallocInit;                 /* True after malloc is initialized */
  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */

  int nSmall;                       /* alloc size threshold used by mem6.c */
  int mxParserStack;                /* maximum depth of the parser stack */
};

/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.







>







1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
  int nScratch;                     /* Number of scratch buffers */
  void *pPage;                      /* Page cache memory */
  int szPage;                       /* Size of each page in pPage[] */
  int nPage;                        /* Number of pages in pPage[] */
  int isInit;                       /* True after initialization has finished */
  int isMallocInit;                 /* True after malloc is initialized */
  sqlite3_mutex *pInitMutex;        /* Mutex used by sqlite3_initialize() */
  int nRefInitMutex;                /* Number of users of pInitMutex */
  int nSmall;                       /* alloc size threshold used by mem6.c */
  int mxParserStack;                /* maximum depth of the parser stack */
};

/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex_methods *sqlite3DefaultMutex(void);
  sqlite3_mutex *sqlite3MutexAlloc(int);
  int sqlite3MutexInit(void);
  int sqlite3MutexEnd(void);
#endif

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

int sqlite3IsNaN(double);

void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);







<







1895
1896
1897
1898
1899
1900
1901

1902
1903
1904
1905
1906
1907
1908
#ifndef SQLITE_MUTEX_NOOP
  sqlite3_mutex_methods *sqlite3DefaultMutex(void);
  sqlite3_mutex *sqlite3MutexAlloc(int);
  int sqlite3MutexInit(void);
  int sqlite3MutexEnd(void);
#endif


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

int sqlite3IsNaN(double);

void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
Changes to src/status.c.
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
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This module implements the sqlite3_status() interface and related
** functionality.
**
** $Id: status.c,v 1.7 2008/08/05 17:53:23 drh Exp $
*/
#include "sqliteInt.h"

/*
** Variables in which to record status information.
*/
static struct {
  int nowValue[9];         /* Current value */
  int mxValue[9];          /* Maximum value */
} sqlite3Stat;


/*
** Reset the status records.  This routine is called by
** sqlite3_initialize().
*/
void sqlite3StatusReset(void){
  memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
}

/*
** Return the current value of a status parameter.
*/
int sqlite3StatusValue(int op){
  assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
  return sqlite3Stat.nowValue[op];
}







|












<
<
<
<
<
<
<
<







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
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This module implements the sqlite3_status() interface and related
** functionality.
**
** $Id: status.c,v 1.8 2008/08/12 15:21:12 drh Exp $
*/
#include "sqliteInt.h"

/*
** Variables in which to record status information.
*/
static struct {
  int nowValue[9];         /* Current value */
  int mxValue[9];          /* Maximum value */
} sqlite3Stat;










/*
** Return the current value of a status parameter.
*/
int sqlite3StatusValue(int op){
  assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
  return sqlite3Stat.nowValue[op];
}
Changes to test/memsubsys1.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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.8 2008/08/04 20:13:27 drh Exp $

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

# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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.9 2008/08/12 15:21:12 drh Exp $

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

# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
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
    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_config_lookaside 0 0
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







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







>
















>







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
    db eval {DELETE FROM t2}
  }
  do_test $testname.1 {
    db eval {SELECT count(*) FROM t1}
  } 8192
  integrity_check $testname.2
}

# Reset all of the highwater marks.
#
proc reset_highwater_marks {} {
  sqlite3_status SQLITE_STATUS_MEMORY_USED 1
  sqlite3_status SQLITE_STATUS_MALLOC_SIZE 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 1
  sqlite3_status SQLITE_STATUS_SCRATCH_USED 1
  sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 1
  sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 1
  sqlite3_status SQLITE_STATUS_PARSER_STACK 1
}

# Test 1:  Both PAGECACHE and SCRATCH are shut down.
#
db close
sqlite3_shutdown
sqlite3_config_lookaside 0 0
sqlite3_initialize
reset_highwater_marks
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
reset_highwater_marks
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
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
# 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]
} 19
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]
} 49
do_test memsubsys1-4.4 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]







>















>



















>







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
# 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
reset_highwater_marks
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
reset_highwater_marks
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]
} 19
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
reset_highwater_marks
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]
} 49
do_test memsubsys1-4.4 {
  set pg_ovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 2]
145
146
147
148
149
150
151

152
153
154
155
156
157
158
# 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]
} 23
do_test memsubsys1-5.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]







>







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# such that the SCRATCH allocations are too small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 6000 2
sqlite3_initialize
reset_highwater_marks
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]
} 23
do_test memsubsys1-5.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
170
171
172
173
174
175
176

177
178
179
180
181
182
183
# 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]
} 23
do_test memsubsys1-6.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]







>







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# Make it so that SCRATCH is large enough
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
reset_highwater_marks
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]
} 23
do_test memsubsys1-6.4 {
  set maxreq [lindex [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0] 2]
194
195
196
197
198
199
200

201
202
203
204
205
206
207
# that maximum allocation size is small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize

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 {







>







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# that maximum allocation size is small.
#
db close
sqlite3_shutdown
sqlite3_config_pagecache 4096 24
sqlite3_config_scratch 25000 1
sqlite3_initialize
reset_highwater_marks
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 {
Changes to test/memsubsys2.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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: memsubsys2.test,v 1.1 2008/07/10 18:13:43 drh Exp $

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

# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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: memsubsys2.test,v 1.2 2008/08/12 15:21:12 drh Exp $

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

# This procedure constructs a new database in test.db.  It fills
# this database with many small records (enough to force multiple
40
41
42
43
44
45
46














47
48
49
50
51
52
53
    db eval {DELETE FROM t2}
  }
  do_test $testname.1 {
    db eval {SELECT count(*) FROM t1}
  } 8192
  integrity_check $testname.2
}















# Test 1:  Verify that calling sqlite3_malloc(0) returns a NULL
# pointer.
#
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-1.1 {
  sqlite3_malloc 0







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







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
    db eval {DELETE FROM t2}
  }
  do_test $testname.1 {
    db eval {SELECT count(*) FROM t1}
  } 8192
  integrity_check $testname.2
}

# Reset all of the highwater marks.
#
proc reset_highwater_marks {} {
  sqlite3_status SQLITE_STATUS_MEMORY_USED 1
  sqlite3_status SQLITE_STATUS_MALLOC_SIZE 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 1
  sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 1
  sqlite3_status SQLITE_STATUS_SCRATCH_USED 1
  sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 1
  sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 1
  sqlite3_status SQLITE_STATUS_PARSER_STACK 1
}

# Test 1:  Verify that calling sqlite3_malloc(0) returns a NULL
# pointer.
#
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-1.1 {
  sqlite3_malloc 0
73
74
75
76
77
78
79

80
81
82
83
84
85
86
# Test 3: Verify that turning of memstatus disables the statistics
# tracking.
#
db close
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_initialize

set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-3.1 {
  set highwater
} {0}
do_test memsubsys2-3.2 {
  sqlite3_malloc 0
} {0}







>







87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Test 3: Verify that turning of memstatus disables the statistics
# tracking.
#
db close
sqlite3_shutdown
sqlite3_config_memstatus 0
sqlite3_initialize
reset_highwater_marks
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-3.1 {
  set highwater
} {0}
do_test memsubsys2-3.2 {
  sqlite3_malloc 0
} {0}
110
111
112
113
114
115
116

117
118
119
120
121
122
123

# Test 4: Verify that turning on memstatus reenables the statistics
# tracking.
#
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_initialize

set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-4.1 {
  set highwater
} {0}
do_test memsubsys2-4.2 {
  sqlite3_malloc 0
} {0}







>







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

# Test 4: Verify that turning on memstatus reenables the statistics
# tracking.
#
sqlite3_shutdown
sqlite3_config_memstatus 1
sqlite3_initialize
reset_highwater_marks
set highwater [sqlite3_memory_highwater 0]
do_test memsubsys2-4.1 {
  set highwater
} {0}
do_test memsubsys2-4.2 {
  sqlite3_malloc 0
} {0}