/ Check-in [b8451da3]
Login

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

Overview
Comment: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)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b8451da378179d43f25d9a014480c0f13dd1dc37
User & Date: drh 2007-08-24 16:08:29
Context
2007-08-24
16:29
Fix bugs in temp database handling introduced by the prevous check-in. (CVS 4288) check-in: 300038be user: drh tags: trunk
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: b8451da3 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: 13dda2e8 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
....
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
**
*************************************************************************
** 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.397 2007/08/24 03:51:34 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The version of the library
*/
................................................................................
  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqlite3_free(db->aDb[1].pSchema);
  sqlite3_vfs_release(db->pVfs);
  sqlite3_mutex_leave(db->mutex);
  sqlite3_mutex_free(db->mutex);
  sqlite3_free(db);
  return SQLITE_OK;
}

/*
................................................................................
  int rc;
  pVfs = sqlite3_vfs_find(0);

  /* This function works in milliseconds, but the underlying OsSleep() 
  ** API uses microseconds. Hence the 1000's.
  */
  rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);
  sqlite3_vfs_release(pVfs);
  return rc;
}

/*
** Enable or disable the extended result codes.
*/
int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
  sqlite3_mutex_enter(db->mutex);
  db->errMask = onoff ? 0xffffffff : 0xff;
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}







|







 







<







 







<












10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
216
217
218
219
220
221
222

223
224
225
226
227
228
229
....
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
**
*************************************************************************
** 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.398 2007/08/24 16:08:29 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The version of the library
*/
................................................................................
  /* The temp-database schema is allocated differently from the other schema
  ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
  ** So it needs to be freed here. Todo: Why not roll the temp schema into
  ** the same sqliteMalloc() as the one that allocates the database 
  ** structure?
  */
  sqlite3_free(db->aDb[1].pSchema);

  sqlite3_mutex_leave(db->mutex);
  sqlite3_mutex_free(db->mutex);
  sqlite3_free(db);
  return SQLITE_OK;
}

/*
................................................................................
  int rc;
  pVfs = sqlite3_vfs_find(0);

  /* This function works in milliseconds, but the underlying OsSleep() 
  ** API uses microseconds. Hence the 1000's.
  */
  rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000);

  return rc;
}

/*
** Enable or disable the extended result codes.
*/
int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
  sqlite3_mutex_enter(db->mutex);
  db->errMask = onoff ? 0xffffffff : 0xff;
  sqlite3_mutex_leave(db->mutex);
  return SQLITE_OK;
}

Changes to src/os.c.

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
    vfsList = sqlite3OsDefaultVfs();
    isInit = 1;
  }
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;
  }
  if( pVfs ){
    pVfs->nRef++;
    assert( pVfs->nRef==1 || pVfs->vfsMutex!=0 );
    assert( pVfs->nRef>1 || pVfs->vfsMutex==0 );
    if( pVfs->vfsMutex==0 ){
      pVfs->vfsMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
    }
  }
  sqlite3_mutex_leave(mutex);
  return pVfs;
}

/*
** Release a VFS once it is no longer needed.
*/
int sqlite3_vfs_release(sqlite3_vfs *pVfs){
  sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
  sqlite3_mutex_enter(mutex);
  assert( pVfs->nRef>0 );
  pVfs->nRef--;
  if( pVfs->nRef==0 && pVfs->vfsMutex ){
    sqlite3_mutex_free(pVfs->vfsMutex);
    pVfs->vfsMutex = 0;
  }
  sqlite3_mutex_leave(mutex);
  return SQLITE_OK;
}

/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
  if( vfsList==pVfs ){
    vfsList = pVfs->pNext;







<
<
<
<
<
<
<
<




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







195
196
197
198
199
200
201








202
203
204
205
















206
207
208
209
210
211
212
    vfsList = sqlite3OsDefaultVfs();
    isInit = 1;
  }
  for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
    if( zVfs==0 ) break;
    if( strcmp(zVfs, pVfs->zName)==0 ) break;
  }








  sqlite3_mutex_leave(mutex);
  return pVfs;
}

















/*
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
  assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) );
  if( vfsList==pVfs ){
    vfsList = pVfs->pNext;

Changes to src/os_unix.c.

2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
** initialized structures.
*/
sqlite3_vfs *sqlite3OsDefaultVfs(void){
  static sqlite3_vfs unixVfs = {
    1,                  /* iVersion */
    sizeof(unixFile),   /* szOsFile */
    MAX_PATHNAME,       /* mxPathname */
    0,                  /* nRef */
    0,                  /* vfsMutex */
    0,                  /* pNext */
    "unix",             /* zName */
    0,                  /* pAppData */
  
    unixOpen,           /* xOpen */
    unixDelete,         /* xDelete */
    unixAccess,         /* xAccess */







<
<







2698
2699
2700
2701
2702
2703
2704


2705
2706
2707
2708
2709
2710
2711
** initialized structures.
*/
sqlite3_vfs *sqlite3OsDefaultVfs(void){
  static sqlite3_vfs unixVfs = {
    1,                  /* iVersion */
    sizeof(unixFile),   /* szOsFile */
    MAX_PATHNAME,       /* mxPathname */


    0,                  /* pNext */
    "unix",             /* zName */
    0,                  /* pAppData */
  
    unixOpen,           /* xOpen */
    unixDelete,         /* xDelete */
    unixAccess,         /* xAccess */

Changes to src/os_win.c.

1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
** initialized structures.
*/
sqlite3_vfs *sqlite3OsDefaultVfs(void){
  static sqlite3_vfs winVfs = {
    1,                 /* iVersion */
    sizeof(winFile),   /* szOsFile */
    MAX_PATH,          /* mxPathname */
    0,                 /* nRef */
    0,                 /* vfsMutex */
    0,                 /* pNext */
    "win32",           /* zName */
    0,                 /* pAppData */
  
    winOpen,           /* xOpen */
    winDelete,         /* xDelete */
    winAccess,         /* xAccess */







<
<







1461
1462
1463
1464
1465
1466
1467


1468
1469
1470
1471
1472
1473
1474
** initialized structures.
*/
sqlite3_vfs *sqlite3OsDefaultVfs(void){
  static sqlite3_vfs winVfs = {
    1,                 /* iVersion */
    sizeof(winFile),   /* szOsFile */
    MAX_PATH,          /* mxPathname */


    0,                 /* pNext */
    "win32",           /* zName */
    0,                 /* pAppData */
  
    winOpen,           /* xOpen */
    winDelete,         /* xDelete */
    winAccess,         /* xAccess */

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
....
1877
1878
1879
1880
1881
1882
1883
1884


1885
1886
1887
























1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
1904
1905
1906


1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
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
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
....
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
....
2003
2004
2005
2006
2007
2008
2009
2010
2011

2012
2013
2014
2015
2016
2017
2018
....
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
** 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>

/*
................................................................................
/*
** 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(
................................................................................
  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 */
    journalFileSize +           /* The journal file structure */ 
    pVfs->szOsFile * 2 +        /* The db and stmt journal files */ 
    pVfs->mxPathname * 3 + 30   /* zFilename, zDirectory, zJournal */
  );
  if( !pPager ){

    return SQLITE_NOMEM;
  }
  pPtr = (u8 *)&pPager[1];
  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
  pPager->zDirectory = &pPager->zFilename[pVfs->mxPathname];
  pPager->zJournal = &pPager->zDirectory[pVfs->mxPathname];
  pPager->pVfs = pVfs;



  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      pPager->zFilename[0] = '\0';
    }else
#endif
    {
      rc = sqlite3OsFullPathname(pVfs, zFilename, pPager->zFilename);
      if( rc==SQLITE_OK ){
        if( strlen(pPager->zFilename)>(pVfs->mxPathname - strlen("-journal")) ){

          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;
  }
................................................................................
    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
  }

  PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, pVfs->mxPathname);
  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;

  /* Fill in Pager.zJournal[] */
  memcpy(pPager->zJournal, pPager->zFilename, pVfs->mxPathname);
  memcpy(&pPager->zJournal[strlen(pPager->zJournal)], "-journal", 9);

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

  /* pPager->errMask = 0; */
  pPager->tempFile = tempFile;
  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
  pPager->exclusiveMode = tempFile; 
  pPager->memDb = memDb;
................................................................................
      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);







|







 







|







 







|
>
>



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






|


>







|
|

>
>



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

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
<
<
|







 







|




|
|







 







<

>







 







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
....
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
....
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
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
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
1979
1980
1981


1982
1983
1984
1985
1986
1987
1988
1989
....
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
....
2024
2025
2026
2027
2028
2029
2030

2031
2032
2033
2034
2035
2036
2037
2038
2039
....
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
** 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.375 2007/08/24 16:08:29 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include <assert.h>
#include <string.h>

/*
................................................................................
/*
** 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(
................................................................................
  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;
  char *zPathname;
  int nPathname;

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

  /* Compute the full pathname */
  zPathname = sqlite3_malloc(pVfs->mxPathname+1);
  if( zPathname==0 ){
    return SQLITE_NOMEM;
  }
  if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
    if( strcmp(zFilename,":memory:")==0 ){
      memDb = 1;
      zPathname[0] = 0;
    }else
#endif
    {
      rc = sqlite3OsFullPathname(pVfs, zFilename, zPathname);
      if( rc!=SQLITE_OK ){
        sqlite3_free(zPathname);
        return rc;
      }
    }
  }else{
    zPathname[0] = 0;
  }
  nPathname = strlen(zPathname);

  /* Allocate memory for the pager structure */
  pPager = sqlite3MallocZero(
    sizeof(*pPager) +           /* Pager structure */
    journalFileSize +           /* The journal file structure */ 
    pVfs->szOsFile * 2 +        /* The db and stmt journal files */ 
    nPathname * 3 + 30          /* zFilename, zDirectory, zJournal */
  );
  if( !pPager ){
    sqlite3_free(zPathname);
    return SQLITE_NOMEM;
  }
  pPtr = (u8 *)&pPager[1];
  pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
  pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
  pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
  pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
  pPager->zDirectory = &pPager->zFilename[nPathname+1];
  pPager->zJournal = &pPager->zDirectory[nPathname+1];
  pPager->pVfs = pVfs;
  memcpy(pPager->zFilename, zPathname, nPathname+1);
  sqlite3_free(zPathname);

  /* Open the pager file.
  */




  if( pPager->zFilename[0] ){






    if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
      rc = SQLITE_CANTOPEN;
    }else{
/***  FIXME:  Might need to be SQLITE_OPEN_TEMP_DB.  Need to pass in
**** a flag from higher up.
****/
      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( !memDb ){
    /* 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;
  }
................................................................................
    return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
  }

  PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
  IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))

  /* Fill in Pager.zDirectory[] */
  memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
  for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
  if( i>0 ) pPager->zDirectory[i-1] = 0;

  /* Fill in Pager.zJournal[] */
  memcpy(pPager->zJournal, pPager->zFilename, nPathname);
  memcpy(&pPager->zJournal[nPathname], "-journal", 9);

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

  /* pPager->state = PAGER_UNLOCK; */
  assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
  /* pPager->errMask = 0; */
  pPager->tempFile = tempFile;
  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
  pPager->exclusiveMode = tempFile; 
  pPager->memDb = memDb;
................................................................................
      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/sqlite.h.in.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558






559
560
561
562
563
564
565
...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
....
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
** 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.239 2007/08/24 03:51:34 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++.
................................................................................
** versions of SQLite.  Additional fields may be appended to this
** object when the iVersion value is increased.
**
** The szOsFile field is the size of the subclassed sqlite3_file
** structure used by this VFS.  mxPathname is the maximum length of
** a pathname in this VFS.
**
** The nRef field is incremented and decremented by SQLite to keep
** count of the number of users of the VFS.  This field and
** vfsMutex, pNext, and pPrev are the only fields in the sqlite3_vfs 
** structure that SQLite will ever modify.  SQLite will only access
** or modify these fields while holding a particular static mutex.
** The application should never modify any fields of the sqlite3_vfs
** object once the object has been registered.
** 
** The sqlite3_vfs.vfsMutex is a mutex used by the OS interface.
** It should initially be NULL.  SQLite will initialize this field
** using sqlite3_mutex_alloc() upon first use of the adaptor
** by sqlite3_open_v2() and will deallocate the mutex when the
** last user closes.  In other words, vfsMutex will be allocated
** when nRef transitions from 0 to 1 and will be deallocated when
** nRef transitions from 1 to 0.
**
** Registered vfs modules are kept on a linked list formed by
** the pNext pointer.  The [sqlite3_register_vfs()]
** and [sqlite3_unregister_vfs()] interfaces manage this list
** in a thread-safe way.  The [sqlite3_find_vfs()] interface
** searches the list.






**
** The zName field holds the name of the VFS module.  The name must
** be unique across all VFS modules.
**
** SQLite will guarantee that the zFilename string passed to
** xOpen() is a full pathname as generated by xFullPathname() and
** that the string will be valid and unchanged until xClose() is
................................................................................
** time.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
  int iVersion;            /* Structure version number */
  int szOsFile;            /* Size of subclassed sqlite3_file */
  int mxPathname;          /* Maximum file pathname length */
  int nRef;                /* Number of references to this structure */
  sqlite3_mutex *vfsMutex; /* A mutex for this VFS */
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Application context */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags);
  int (*xGetTempName)(sqlite3_vfs*, char *zOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
................................................................................
** single default VFS that is appropriate for the host computer.
** New VFSes can be registered and existing VFSes can be unregistered.
** The following interfaces are provided.
**
** The sqlite3_vfs_find() interface returns a pointer to a VFS given its
** name.  Names are case sensitive.  If there is no match, a NULL
** pointer is returned.  If zVfsName is NULL then the default 
** VFS is returned.  If a valid VFS pointer is returned, its
** vfsMutex field will have been initialized and nRef will be
** greater than zero.  The sqlite3_vfs_release() function should
** be used to release the VFS when it is no longer needed.
**
** New VFSes are registered with sqlite3_vfs_register().  Each
** new VFS becomes the default VFS if the makeDflt flag is set.
** The same VFS can be registered multiple times without injury.
** To make an existing VFS into the default VFS, register it again
** with the makeDflt flag set.
** 
** Unregister a VFS with the sqlite3_vfs_unregister() interface.
** If the default VFS is unregistered, another VFS is chosen as
** the default.  The choice for the new VFS is arbitrary.
*/
sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
int sqlite3_vfs_release(sqlite3_vfs*);
int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
int sqlite3_vfs_unregister(sqlite3_vfs*);

/*
** CAPI3REF: Mutexes
**
** The SQLite core uses these routines for thread







|







 







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





>
>
>
>
>
>







 







<
<


|







 







|
<
<
<












<







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
531
532
533
534
535
536
537
















538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
...
625
626
627
628
629
630
631


632
633
634
635
636
637
638
639
640
641
....
3197
3198
3199
3200
3201
3202
3203
3204



3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216

3217
3218
3219
3220
3221
3222
3223
** 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.240 2007/08/24 16:08:29 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++.
................................................................................
** versions of SQLite.  Additional fields may be appended to this
** object when the iVersion value is increased.
**
** The szOsFile field is the size of the subclassed sqlite3_file
** structure used by this VFS.  mxPathname is the maximum length of
** a pathname in this VFS.
**
















** Registered vfs modules are kept on a linked list formed by
** the pNext pointer.  The [sqlite3_register_vfs()]
** and [sqlite3_unregister_vfs()] interfaces manage this list
** in a thread-safe way.  The [sqlite3_find_vfs()] interface
** searches the list.
**
** The pNext field is the only fields in the sqlite3_vfs 
** structure that SQLite will ever modify.  SQLite will only access
** or modify this field while holding a particular static mutex.
** The application should never modify anything within the sqlite3_vfs
** object once the object has been registered.
**
** The zName field holds the name of the VFS module.  The name must
** be unique across all VFS modules.
**
** SQLite will guarantee that the zFilename string passed to
** xOpen() is a full pathname as generated by xFullPathname() and
** that the string will be valid and unchanged until xClose() is
................................................................................
** time.
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
  int iVersion;            /* Structure version number */
  int szOsFile;            /* Size of subclassed sqlite3_file */
  int mxPathname;          /* Maximum file pathname length */


  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags);
  int (*xGetTempName)(sqlite3_vfs*, char *zOut);
  int (*xFullPathname)(sqlite3_vfs*, const char *zName, char *zOut);
  void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
................................................................................
** single default VFS that is appropriate for the host computer.
** New VFSes can be registered and existing VFSes can be unregistered.
** The following interfaces are provided.
**
** The sqlite3_vfs_find() interface returns a pointer to a VFS given its
** name.  Names are case sensitive.  If there is no match, a NULL
** pointer is returned.  If zVfsName is NULL then the default 
** VFS is returned.



**
** New VFSes are registered with sqlite3_vfs_register().  Each
** new VFS becomes the default VFS if the makeDflt flag is set.
** The same VFS can be registered multiple times without injury.
** To make an existing VFS into the default VFS, register it again
** with the makeDflt flag set.
** 
** Unregister a VFS with the sqlite3_vfs_unregister() interface.
** If the default VFS is unregistered, another VFS is chosen as
** the default.  The choice for the new VFS is arbitrary.
*/
sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);

int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
int sqlite3_vfs_unregister(sqlite3_vfs*);

/*
** CAPI3REF: Mutexes
**
** The SQLite core uses these routines for thread

Changes to src/test3.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.81 2007/08/22 02:56:44 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
    return TCL_ERROR;
  }
  nRefSqlite3--;
  if( nRefSqlite3==0 ){
    sqlite3_mutex_leave(sDb.mutex);
    sqlite3_mutex_free(sDb.mutex);
    sDb.mutex = 0;
    sqlite3_vfs_release(sDb.pVfs);
    sDb.pVfs = 0;
  }
  return TCL_OK;
}


/*







|







 







<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
116
117
118
119
120
121
122

123
124
125
126
127
128
129
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.82 2007/08/24 16:08:29 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
    return TCL_ERROR;
  }
  nRefSqlite3--;
  if( nRefSqlite3==0 ){
    sqlite3_mutex_leave(sDb.mutex);
    sqlite3_mutex_free(sDb.mutex);
    sDb.mutex = 0;

    sDb.pVfs = 0;
  }
  return TCL_OK;
}


/*

Changes to src/test6.c.

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  const char *zCrashFile;
  int nCrashFile, iDc, iSectorSize;

  static sqlite3_vfs crashVfs = {
    1,                  /* iVersion */
    0,                  /* szOsFile */
    0,                  /* mxPathname */
    0,                  /* nRef */
    0,                  /* vfsMutex */
    0,                  /* pNext */
    "crash",            /* zName */
    0,                  /* pAppData */
  
    cfOpen,               /* xOpen */
    cfDelete,             /* xDelete */
    cfAccess,             /* xAccess */
................................................................................
    sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
    crashVfs.xDlError = pOriginalVfs->xDlError;
    crashVfs.xDlSym = pOriginalVfs->xDlSym;
    crashVfs.xDlClose = pOriginalVfs->xDlClose;
    crashVfs.mxPathname = pOriginalVfs->mxPathname;
    crashVfs.pAppData = (void *)pOriginalVfs;
    crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
    sqlite3_vfs_release(pOriginalVfs);
    /* sqlite3_vfs_unregister(pOriginalVfs); */
    sqlite3_vfs_register(&crashVfs, 1);
  }

  iDc = -1;
  iSectorSize = -1;








<
<







 







<







718
719
720
721
722
723
724


725
726
727
728
729
730
731
...
745
746
747
748
749
750
751

752
753
754
755
756
757
758
  const char *zCrashFile;
  int nCrashFile, iDc, iSectorSize;

  static sqlite3_vfs crashVfs = {
    1,                  /* iVersion */
    0,                  /* szOsFile */
    0,                  /* mxPathname */


    0,                  /* pNext */
    "crash",            /* zName */
    0,                  /* pAppData */
  
    cfOpen,               /* xOpen */
    cfDelete,             /* xDelete */
    cfAccess,             /* xAccess */
................................................................................
    sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
    crashVfs.xDlError = pOriginalVfs->xDlError;
    crashVfs.xDlSym = pOriginalVfs->xDlSym;
    crashVfs.xDlClose = pOriginalVfs->xDlClose;
    crashVfs.mxPathname = pOriginalVfs->mxPathname;
    crashVfs.pAppData = (void *)pOriginalVfs;
    crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;

    /* sqlite3_vfs_unregister(pOriginalVfs); */
    sqlite3_vfs_register(&crashVfs, 1);
  }

  iDc = -1;
  iSectorSize = -1;

Changes to test/pager.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
405
406
407
408
409
410
411

412
413
414
415
416
417
418
...
565
566
567
568
569
570
571
572
573
574
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.28 2007/04/05 17:15:53 danielk1977 Exp $


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

if {[info commands pager_open]!=""} {
db close
................................................................................
do_test pager-4.6.1 {
  pager_close [pager_open ptf2.db -15]
} {}

# Test truncate on an in-memory database is Ok.
ifcapable memorydb {
  do_test pager-4.6.2 {

    set ::p2 [pager_open :memory: 10]
    pager_truncate $::p2 5
  } {}
  do_test pager-4.6.3 {
    for {set i 1} {$i<5} {incr i} {
      set p [page_get $::p2 $i]
      page_write $p "Page $i"
................................................................................
} {{CREATE TABLE abc(a, b, c)}}

do_test pager-6.5 {
  db2 close
} {}
}
finish_test










|







 







>







 







<
<
<
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
...
566
567
568
569
570
571
572



#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is page cache subsystem.
#
# $Id: pager.test,v 1.29 2007/08/24 16:08:29 drh Exp $


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

if {[info commands pager_open]!=""} {
db close
................................................................................
do_test pager-4.6.1 {
  pager_close [pager_open ptf2.db -15]
} {}

# Test truncate on an in-memory database is Ok.
ifcapable memorydb {
  do_test pager-4.6.2 {
btree_breakpoint
    set ::p2 [pager_open :memory: 10]
    pager_truncate $::p2 5
  } {}
  do_test pager-4.6.3 {
    for {set i 1} {$i<5} {incr i} {
      set p [page_get $::p2 $i]
      page_write $p "Page $i"
................................................................................
} {{CREATE TABLE abc(a, b, c)}}

do_test pager-6.5 {
  db2 close
} {}
}
finish_test