SQLite

Check-in [13dda2e8e8]
Login

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

Overview
Comment:Select the default page size for new databases based on the sector-size and IOCAP flags. (CVS 4286)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 13dda2e8e879835c21e539ba3ff8f96face1af4c
User & Date: danielk1977 2007-08-24 11:52:29.000
Context
2007-08-24
16:08
Remove nRef and vfsMutex from the sqlite3_vfs structure. Omit the sqlite3_vfs_release() interface. Less memory allocated for a pager in the common case where the size of the pathname is less than MAX_PATH. (CVS 4287) (check-in: b8451da378 user: drh tags: trunk)
11:52
Select the default page size for new databases based on the sector-size and IOCAP flags. (CVS 4286) (check-in: 13dda2e8e8 user: danielk1977 tags: trunk)
11:43
Remove unnecessary sqlite3MallocDisallow() that was preventing win32 from running. (CVS 4285) (check-in: eb6c98fc10 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.411 2007/08/24 03:51:33 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"












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.412 2007/08/24 11:52:29 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
    sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
    pBt->pCursor = 0;
    pBt->pPage1 = 0;
    pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
    pBt->pageSize = get2byte(&zDbHeader[16]);
    if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
         || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
      pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
      pBt->maxEmbedFrac = 64;   /* 25% */
      pBt->minEmbedFrac = 32;   /* 12.5% */
      pBt->minLeafFrac = 32;    /* 12.5% */
#ifndef SQLITE_OMIT_AUTOVACUUM
      /* If the magic name ":memory:" will create an in-memory database, then
      ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
      ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if







|







1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
    sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
    pBt->pCursor = 0;
    pBt->pPage1 = 0;
    pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
    pBt->pageSize = get2byte(&zDbHeader[16]);
    if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
         || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
      pBt->pageSize = sqlite3PagerSetPagesize(pBt->pPager, 0);
      pBt->maxEmbedFrac = 64;   /* 25% */
      pBt->minEmbedFrac = 32;   /* 12.5% */
      pBt->minLeafFrac = 32;    /* 12.5% */
#ifndef SQLITE_OMIT_AUTOVACUUM
      /* If the magic name ":memory:" will create an in-memory database, then
      ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if
      ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.373 2007/08/24 08:15:54 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.374 2007/08/24 11:52:29 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist.  The file is not locked until
** the first call to sqlite3PagerGet() and is only held open until the
** last page is released using sqlite3PagerUnref().
**
** If zFilename is NULL then a randomly-named temporary file is created
** and used as the file to be cached.  The file will be deleted
** automatically when it is closed.
**
** If zFilename is ":memory:" then all information is held in cache.
** It is never written to disk.  This can be used to implement an
** in-memory database.
*/
int sqlite3PagerOpen(







|







1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist.  The file is not locked until
** the first call to sqlite3PagerGet() and is only held open until the
** last page is released using sqlite3PagerUnref().
**
** If zFilename is NULL then a randomly-named temporary file is created
** and
** automatically when it is closed.
**
** If zFilename is ":memory:" then all information is held in cache.
** It is never written to disk.  This can be used to implement an
** in-memory database.
*/
int sqlite3PagerOpen(
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
  int i;
  int tempFile = 0;
  int memDb = 0;
  int readOnly = 0;
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
  int journalFileSize = sqlite3JournalSize(pVfs);


  /* The default return is a NULL pointer */
  *ppPager = 0;

  /* Allocate memory for the pager structure */
  pPager = sqlite3MallocZero(
    sizeof(*pPager) +           /* Pager structure */







>







1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
  int i;
  int tempFile = 0;
  int memDb = 0;
  int readOnly = 0;
  int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
  int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
  int journalFileSize = sqlite3JournalSize(pVfs);
  int nDefaultPage = SQLITE_DEFAULT_PAGE_SIZE;     /* Default page size. */

  /* The default return is a NULL pointer */
  *ppPager = 0;

  /* Allocate memory for the pager structure */
  pPager = sqlite3MallocZero(
    sizeof(*pPager) +           /* Pager structure */
1920
1921
1922
1923
1924
1925
1926






























1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
          rc = SQLITE_CANTOPEN;
        }else{
          int oflag = 
              (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB);
          int fout = 0;
          rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, oflag, &fout);
          readOnly = (fout&SQLITE_OPEN_READONLY);






























        }
      }
    }
  }else{
    /* If a temporary file is requested, it is not opened immediately.
    ** In this case we accept the default page size and delay actually
    ** opening the file until the first call to OsWrite().
    */ 
    tempFile = 1;
    pPager->state = PAGER_EXCLUSIVE;
  }

  if( pPager && rc==SQLITE_OK ){
    pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE);
  }

  /* If an error occured in either of the blocks above.
  ** Free the Pager structure and close the file.
  ** Since the pager is not allocated there is no need to set 
  ** any Pager.errMask variables.
  */







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













|







1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
          rc = SQLITE_CANTOPEN;
        }else{
          int oflag = 
              (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB);
          int fout = 0;
          rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, oflag, &fout);
          readOnly = (fout&SQLITE_OPEN_READONLY);
 
          /* If the file was successfully opened for read/write access,
          ** choose a default page size in case we have to create the
          ** database file. The default page size is the maximum of:
          **
          **    + SQLITE_DEFAULT_PAGE_SIZE,
          **    + The value returned by sqlite3OsSectorSize()
          **    + The largest page size that can be written atomically.
          */
          if( rc==SQLITE_OK && !readOnly ){
            int iSectorSize = sqlite3OsSectorSize(pPager->fd);
            if( nDefaultPage<iSectorSize ){
              nDefaultPage = iSectorSize;
            }
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
            {
              int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
              int ii;
              assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
              assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
              assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
              for(ii=nDefaultPage; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
                if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ) nDefaultPage = ii;
              }
            }
#endif
            if( nDefaultPage>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
              nDefaultPage = SQLITE_MAX_DEFAULT_PAGE_SIZE;
            }
          }
        }
      }
    }
  }else{
    /* If a temporary file is requested, it is not opened immediately.
    ** In this case we accept the default page size and delay actually
    ** opening the file until the first call to OsWrite().
    */ 
    tempFile = 1;
    pPager->state = PAGER_EXCLUSIVE;
  }

  if( pPager && rc==SQLITE_OK ){
    pPager->pTmpSpace = (char *)sqlite3_malloc(nDefaultPage);
  }

  /* If an error occured in either of the blocks above.
  ** Free the Pager structure and close the file.
  ** Since the pager is not allocated there is no need to set 
  ** any Pager.errMask variables.
  */
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
  /* pPager->journalOpen = 0; */
  pPager->useJournal = useJournal && !memDb;
  pPager->noReadlock = noReadlock && readOnly;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
  pPager->dbSize = memDb-1;
  pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE;
  /* pPager->stmtSize = 0; */
  /* pPager->stmtJSize = 0; */
  /* pPager->nPage = 0; */
  pPager->mxPage = 100;
  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
  assert( PAGER_UNLOCK==0 );
  /* pPager->state = PAGER_UNLOCK; */







|







1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
  /* pPager->journalOpen = 0; */
  pPager->useJournal = useJournal && !memDb;
  pPager->noReadlock = noReadlock && readOnly;
  /* pPager->stmtOpen = 0; */
  /* pPager->stmtInUse = 0; */
  /* pPager->nRef = 0; */
  pPager->dbSize = memDb-1;
  pPager->pageSize = nDefaultPage;
  /* pPager->stmtSize = 0; */
  /* pPager->stmtJSize = 0; */
  /* pPager->nPage = 0; */
  pPager->mxPage = 100;
  pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
  assert( PAGER_UNLOCK==0 );
  /* pPager->state = PAGER_UNLOCK; */
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063

2064
2065
2066
2067
2068
2069
2070

/*
** Set the page size.  Return the new size.  If the suggest new page
** size is inappropriate, then an alternative page size is selected
** and returned.
*/
int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){
  assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE );
  if( !pPager->memDb && pPager->nRef==0 ){
    pagerEnter(pPager);
    pager_reset(pPager);
    pPager->pageSize = pageSize;

    pagerLeave(pPager);
    sqlite3_free(pPager->pTmpSpace);
    pPager->pTmpSpace = sqlite3_malloc(pageSize);
  }
  return pPager->pageSize;
}








|
|



>







2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

/*
** Set the page size.  Return the new size.  If the suggest new page
** size is inappropriate, then an alternative page size is selected
** and returned.
*/
int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){
  assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
  if( pageSize && !pPager->memDb && pPager->nRef==0 ){
    pagerEnter(pPager);
    pager_reset(pPager);
    pPager->pageSize = pageSize;
    setSectorSize(pPager);
    pagerLeave(pPager);
    sqlite3_free(pPager->pTmpSpace);
    pPager->pTmpSpace = sqlite3_malloc(pageSize);
  }
  return pPager->pageSize;
}

4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
      while( pPg && !pPg->dirty ){ pPg = pPg->pDirty; }
      pPager->pDirty = pPg;
      goto sync_exit;
    }
    pPager->pDirty = 0;

    /* Sync the database file. */
    if( !pPager->noSync ){
      rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
    }
    IOTRACE(("DBSYNC %p\n", pPager))

    pPager->state = PAGER_SYNCED;
  }else if( MEMDB && nTrunc!=0 ){
    rc = sqlite3PagerTruncate(pPager, nTrunc);







|







4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
      while( pPg && !pPg->dirty ){ pPg = pPg->pDirty; }
      pPager->pDirty = pPg;
      goto sync_exit;
    }
    pPager->pDirty = 0;

    /* Sync the database file. */
    if( !pPager->noSync ){ 
      rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
    }
    IOTRACE(("DBSYNC %p\n", pPager))

    pPager->state = PAGER_SYNCED;
  }else if( MEMDB && nTrunc!=0 ){
    rc = sqlite3PagerTruncate(pPager, nTrunc);
Changes to src/sqliteLimit.h.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 
** This file defines various limits of what SQLite can process.
**
** @(#) $Id: sqliteLimit.h,v 1.1 2007/06/19 15:23:48 drh Exp $
*/

/*
** The maximum length of a TEXT or BLOB in bytes.   This also
** limits the size of a row in a table or index.
**
** The hard limit is the ability of a 32-bit signed integer







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 
** This file defines various limits of what SQLite can process.
**
** @(#) $Id: sqliteLimit.h,v 1.2 2007/08/24 11:52:29 danielk1977 Exp $
*/

/*
** The maximum length of a TEXT or BLOB in bytes.   This also
** limits the size of a row in a table or index.
**
** The hard limit is the ability of a 32-bit signed integer
126
127
128
129
130
131
132











133
134
135
136
137
138
139
/*
** The default size of a database page.
*/
#ifndef SQLITE_DEFAULT_PAGE_SIZE
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif












/* Maximum page size.  The upper bound on this value is 32768.  This a limit
** imposed by the necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 32768
#endif







>
>
>
>
>
>
>
>
>
>
>







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
/*
** The default size of a database page.
*/
#ifndef SQLITE_DEFAULT_PAGE_SIZE
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif

/*
** Ordinarily, if no value is explicitly provided, SQLite creates databases
** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
** device characteristics (sector-size and atomic write() support),
** SQLite may choose a larger value. This constant is the maximum value
** SQLite will choose on it's own.
*/
#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
#endif

/* Maximum page size.  The upper bound on this value is 32768.  This a limit
** imposed by the necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 32768
#endif
Changes to src/vdbeaux.c.
1188
1189
1190
1191
1192
1193
1194
1195
1196


1197
1198

1199
1200
1201
1202
1203
1204
1205
          sqlite3OsDelete(pVfs, zMaster, 0);
          sqlite3_free(zMaster);
          return rc;
        }
      }
    }


    /* Sync the master journal file. */


    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
    if( (needSync 

     && (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){
      sqlite3OsCloseFree(pMaster);
      sqlite3OsDelete(pVfs, zMaster, 0);
      sqlite3_free(zMaster);
      return rc;
    }








<
|
>
>


>







1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
          sqlite3OsDelete(pVfs, zMaster, 0);
          sqlite3_free(zMaster);
          return rc;
        }
      }
    }


    /* Sync the master journal file. If the IOCAP_SEQUENTIAL device
    ** flag is set this is not required.
    */
    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);
    if( (needSync 
     && (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL))
     && (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){
      sqlite3OsCloseFree(pMaster);
      sqlite3OsDelete(pVfs, zMaster, 0);
      sqlite3_free(zMaster);
      return rc;
    }

Changes to test/crash2.test.
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
#
# The focus of this file is testing the ability of the database to
# uses its rollback journal to recover intact (no database corruption)
# from a power failure during the middle of a COMMIT. Even more
# specifically, the tests in this file verify this functionality
# for storage mediums with various sector sizes.
#
# $Id: crash2.test,v 1.4 2007/04/06 21:42:22 drh Exp $

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

ifcapable !crashtest {
  finish_test
  return
}



# This test is designed to check that the crash-test infrastructure
# can create files that do not consist of an integer number of
# simulated disk blocks (i.e. 3KB file using 2KB disk blocks).
#
do_test crash2-1.1 {
  crashsql -delay 500 -file test.db -blocksize 2048 {
    PRAGMA auto_vacuum=OFF;

    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f;
    COMMIT;
  }
  file size test.db
} {3072}

for {set ii 0} {$ii < 5} {incr ii} {

  # Simple test using the database created above: Create a new
  # table so that page 1 and page 4 are modified. Using a
  # block-size of 2048 and page-size of 1024, this means
  # pages 2 and 3 must also be saved in the journal to avoid
  # risking corruption.
  #
  # The loop is so that this test can be run with a couple
  # of different seeds for the random number generator.
  #
  do_test crash2-1.2.$ii {
    crashsql -file test.db -blocksize 2048 "
      [string repeat {SELECT random();} $ii]
      CREATE TABLE hij(h, i, j);
    "


    db eval {PRAGMA integrity_check}
  } {ok}
}

proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}







|








>
>








>




















|


<
>
>







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
#
# The focus of this file is testing the ability of the database to
# uses its rollback journal to recover intact (no database corruption)
# from a power failure during the middle of a COMMIT. Even more
# specifically, the tests in this file verify this functionality
# for storage mediums with various sector sizes.
#
# $Id: crash2.test,v 1.5 2007/08/24 11:52:29 danielk1977 Exp $

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

ifcapable !crashtest {
  finish_test
  return
}

db close

# This test is designed to check that the crash-test infrastructure
# can create files that do not consist of an integer number of
# simulated disk blocks (i.e. 3KB file using 2KB disk blocks).
#
do_test crash2-1.1 {
  crashsql -delay 500 -file test.db -blocksize 2048 {
    PRAGMA auto_vacuum=OFF;
    PRAGMA page_size=1024;
    BEGIN;
    CREATE TABLE abc AS SELECT 1 AS a, 2 AS b, 3 AS c;
    CREATE TABLE def AS SELECT 1 AS d, 2 AS e, 3 AS f;
    COMMIT;
  }
  file size test.db
} {3072}

for {set ii 0} {$ii < 5} {incr ii} {

  # Simple test using the database created above: Create a new
  # table so that page 1 and page 4 are modified. Using a
  # block-size of 2048 and page-size of 1024, this means
  # pages 2 and 3 must also be saved in the journal to avoid
  # risking corruption.
  #
  # The loop is so that this test can be run with a couple
  # of different seeds for the random number generator.
  #
  do_test crash2-1.2.$ii {
    crashsql -file test.db -blocksize 2048 [subst {
      [string repeat {SELECT random();} $ii]
      CREATE TABLE hij(h, i, j);

    }]
    sqlite3 db test.db
    db eval {PRAGMA integrity_check}
  } {ok}
}

proc signature {} {
  return [db eval {SELECT count(*), md5sum(a), md5sum(b), md5sum(c) FROM abc}]
}
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
  }
  execsql COMMIT
  expr ([file size test.db] / 1024) > 450
} {1}
for {set i 1} {$i < 30} {incr i} {
  set sig [signature]
  set sector [expr 1024 * 1<<($i%4)]

  do_test crash-2.$i.1 {
     crashsql -blocksize $sector -delay [expr $i%5 + 1] -file test.db-journal "
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc SELECT randstr(10,10), 0, 0 FROM abc WHERE random()%2==0;
       DELETE FROM abc WHERE random()%2!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash-2.$i.2 {

    signature
  } $sig
} 


# Test case for crashing during database sync with simulated
# sector-size values from 1024 to 8192.
#
for {set i 1} {$i < 10} {incr i} {
  set sig [signature]
  set sector [expr 1024 * 1<<($i%4)]

  do_test crash-3.$i.1 {
     crashsql -blocksize $sector -file test.db "
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc SELECT randstr(10,10), 0, 0 FROM abc WHERE random()%2==0;
       DELETE FROM abc WHERE random()%2!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash-3.$i.2 {

    signature
  } $sig
} 

finish_test







>
|








|
>











>
|








|
>





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
  }
  execsql COMMIT
  expr ([file size test.db] / 1024) > 450
} {1}
for {set i 1} {$i < 30} {incr i} {
  set sig [signature]
  set sector [expr 1024 * 1<<($i%4)]
  db close
  do_test crash2-2.$i.1 {
     crashsql -blocksize $sector -delay [expr $i%5 + 1] -file test.db-journal "
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc SELECT randstr(10,10), 0, 0 FROM abc WHERE random()%2==0;
       DELETE FROM abc WHERE random()%2!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash2-2.$i.2 {
    sqlite3 db test.db
    signature
  } $sig
} 


# Test case for crashing during database sync with simulated
# sector-size values from 1024 to 8192.
#
for {set i 1} {$i < 10} {incr i} {
  set sig [signature]
  set sector [expr 1024 * 1<<($i%4)]
  db close
  do_test crash2-3.$i.1 {
     crashsql -blocksize $sector -file test.db "
       BEGIN;
       SELECT random() FROM abc LIMIT $i;
       INSERT INTO abc SELECT randstr(10,10), 0, 0 FROM abc WHERE random()%2==0;
       DELETE FROM abc WHERE random()%2!=0;
       COMMIT;
     "
  } {1 {child process exited abnormally}}
  do_test crash2-3.$i.2 {
    sqlite3 db test.db
    signature
  } $sig
} 

finish_test
Changes to test/crash3.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
#
# This file contains tests that verify that SQLite can correctly rollback
# databases after crashes when using the special IO modes triggered 
# by device IOCAP flags.
#
# $Id: crash3.test,v 1.2 2007/08/24 08:15:54 danielk1977 Exp $

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

ifcapable !crashtest {
  finish_test
  return







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
#
# This file contains tests that verify that SQLite can correctly rollback
# databases after crashes when using the special IO modes triggered 
# by device IOCAP flags.
#
# $Id: crash3.test,v 1.3 2007/08/24 11:52:29 danielk1977 Exp $

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

ifcapable !crashtest {
  finish_test
  return
73
74
75
76
77
78
79

80
81
82
83
84
85
86
  for {set ii 0} {$ii < 10} {incr ii} {

    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    do_test crash3-1.$tn.1 {
      execsql {

        BEGIN;
        CREATE TABLE abc(a, b, c);
        INSERT INTO abc VALUES(1, 2, 3);
        COMMIT;
      }
    } {}
    db close







>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  for {set ii 0} {$ii < 10} {incr ii} {

    db close
    file delete -force test.db test.db-journal
    sqlite3 db test.db
    do_test crash3-1.$tn.1 {
      execsql {
        PRAGMA page_size = 1024;
        BEGIN;
        CREATE TABLE abc(a, b, c);
        INSERT INTO abc VALUES(1, 2, 3);
        COMMIT;
      }
    } {}
    db close
Changes to test/io.test.
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
#
#***********************************************************************
#
# The focus of this file is testing some specific characteristics of the 
# IO traffic generated by SQLite (making sure SQLite is not writing out
# more database pages than it has to, stuff like that).
#
# $Id: io.test,v 1.5 2007/08/23 16:27:21 danielk1977 Exp $

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

# Test summary:
#
# io-1.* -  Test that quick-balance does not journal pages unnecessarily.
#
# io-2.* -  Test the "atomic-write optimization".
#
# io-3.* -  Test the IO traffic enhancements triggered when the 
#           IOCAP_SEQUENTIAL device capability flag is set (no 
#           fsync() calls on the journal file).
#
# io-4.* -  Test the IO traffic enhancements triggered when the 
#           IOCAP_SAFE_APPEND device capability flag is set (fewer 
#           fsync() calls on the journal file, no need to set nRec
#           field in the single journal header).



#           

set ::nWrite 0
proc nWrite {db} {
  set bt [btree_from_db $db]
  db_enter $db
  array set stats [btree_pager_stats $bt]







|


















>
>
>







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
#
#***********************************************************************
#
# The focus of this file is testing some specific characteristics of the 
# IO traffic generated by SQLite (making sure SQLite is not writing out
# more database pages than it has to, stuff like that).
#
# $Id: io.test,v 1.6 2007/08/24 11:52:29 danielk1977 Exp $

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

# Test summary:
#
# io-1.* -  Test that quick-balance does not journal pages unnecessarily.
#
# io-2.* -  Test the "atomic-write optimization".
#
# io-3.* -  Test the IO traffic enhancements triggered when the 
#           IOCAP_SEQUENTIAL device capability flag is set (no 
#           fsync() calls on the journal file).
#
# io-4.* -  Test the IO traffic enhancements triggered when the 
#           IOCAP_SAFE_APPEND device capability flag is set (fewer 
#           fsync() calls on the journal file, no need to set nRec
#           field in the single journal header).
#
# io-5.* -  Test that the default page size is selected and used 
#           correctly.
#           

set ::nWrite 0
proc nWrite {db} {
  set bt [btree_from_db $db]
  db_enter $db
  array set stats [btree_pager_stats $bt]
224
225
226
227
228
229
230

231
232
233
234
235
236
237
# is created during execution of the COMMIT statement, so we have to
# use the same technique to check that it is created as in the above 
# block.
file delete -force test2.db test2.db-journal
do_test io-2.7.1 {
  execsql {
    ATTACH 'test2.db' AS aux;

    CREATE TABLE aux.abc2(a, b);
    BEGIN;
    INSERT INTO abc VALUES(9, 10);
  }
  file exists test.db-journal
} {0}
do_test io-2.7.2 {







>







227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# is created during execution of the COMMIT statement, so we have to
# use the same technique to check that it is created as in the above 
# block.
file delete -force test2.db test2.db-journal
do_test io-2.7.1 {
  execsql {
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.page_size = 1024;
    CREATE TABLE aux.abc2(a, b);
    BEGIN;
    INSERT INTO abc VALUES(9, 10);
  }
  file exists test.db-journal
} {0}
do_test io-2.7.2 {
458
459
460
461
462
463
464































465
466
467
468
  #    <jrnl file size> = <jrnl header size> + nPage * (<page-size> + 8)
  #
  # If the journal file contains additional headers, this formula
  # will not predict the size of the journal file.
  #
  file size test.db-journal
} [expr 1024 + (1024+8)*41]
































sqlite3_simulate_device -char {} -sectorsize 0
finish_test








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




462
463
464
465
466
467
468
469
470
471
472
473
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
  #    <jrnl file size> = <jrnl header size> + nPage * (<page-size> + 8)
  #
  # If the journal file contains additional headers, this formula
  # will not predict the size of the journal file.
  #
  file size test.db-journal
} [expr 1024 + (1024+8)*41]

#----------------------------------------------------------------------
# Test cases io-5.* test that the default page size is selected and
# used correctly.
#
set tn 0
foreach {char                 sectorsize pgsize} {
         {}                     512      1024
         {}                    1024      1024
         {}                    2048      2048
         {}                    8192      8192
         {}                   16384      8192
         {atomic}               512      8192
         {atomic512}            512      1024
         {atomic2K}             512      2048
         {atomic2K}            4096      4096
         {atomic2K atomic}      512      8192
         {atomic64K}            512      1024
} {
  incr tn
  db close
  file delete -force test.db test.db-journal
  sqlite3_simulate_device -char $char -sectorsize $sectorsize
  sqlite3 db test.db
  do_test io-5.$tn {
    execsql {
      CREATE TABLE abc(a, b, c);
    }
    expr {[file size test.db]/2}
  } $pgsize
}

sqlite3_simulate_device -char {} -sectorsize 0
finish_test