SQLite

Check-in [21510a66dc]
Login

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

Overview
Comment:In the Win32 VFS, when truncating a file, unmap it first.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 21510a66dce4d0843ccfe20f092a01f5a52563ef244a94f1d5d2563305cab925
User & Date: mistachkin 2018-07-22 06:25:35.628
Context
2018-07-22
20:24
Fix harmless compiler warning. (check-in: ead4762dfc user: mistachkin tags: trunk)
06:25
In the Win32 VFS, when truncating a file, unmap it first. (check-in: 21510a66dc user: mistachkin tags: trunk)
2018-07-21
23:15
In 'resetdb.test', close a database prior to trying to delete it. (check-in: 45137053a5 user: mistachkin tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os_win.c.
2900
2901
2902
2903
2904
2905
2906



2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920









2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938

2939

2940
2941
2942
2943
2944
2945
2946
/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  winFile *pFile = (winFile*)id;  /* File handle object */
  int rc = SQLITE_OK;             /* Return code for this function */
  DWORD lastErrno;




  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);
  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
           osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));

  /* If the user has configured a chunk-size for this file, truncate the
  ** file so that it consists of an integer number of chunks (i.e. the
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }










  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( winSeekFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate1", pFile->zPath);
  }else if( 0==osSetEndOfFile(pFile->h) &&
            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
    pFile->lastErrno = lastErrno;
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate2", pFile->zPath);
  }

#if SQLITE_MAX_MMAP_SIZE>0
  /* If the file was truncated to a size smaller than the currently
  ** mapped region, reduce the effective mapping size as well. SQLite will
  ** use read() and write() to access data beyond this point from now on.
  */
  if( pFile->pMapRegion && nByte<pFile->mmapSize ){

    pFile->mmapSize = nByte;

  }
#endif

  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
           osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
  return rc;
}







>
>
>














>
>
>
>
>
>
>
>
>













|
|
<
<
|
>
|
>







2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947


2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
/*
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
  winFile *pFile = (winFile*)id;  /* File handle object */
  int rc = SQLITE_OK;             /* Return code for this function */
  DWORD lastErrno;
#if SQLITE_MAX_MMAP_SIZE>0
  sqlite3_int64 oldMmapSize;
#endif

  assert( pFile );
  SimulateIOError(return SQLITE_IOERR_TRUNCATE);
  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
           osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));

  /* If the user has configured a chunk-size for this file, truncate the
  ** file so that it consists of an integer number of chunks (i.e. the
  ** actual file size after the operation may be larger than the requested
  ** size).
  */
  if( pFile->szChunk>0 ){
    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
  }

#if SQLITE_MAX_MMAP_SIZE>0
  if( pFile->pMapRegion ){
    oldMmapSize = pFile->mmapSize;
  }else{
    oldMmapSize = 0;
  }
  winUnmapfile(pFile);
#endif

  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  if( winSeekFile(pFile, nByte) ){
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate1", pFile->zPath);
  }else if( 0==osSetEndOfFile(pFile->h) &&
            ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
    pFile->lastErrno = lastErrno;
    rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
                     "winTruncate2", pFile->zPath);
  }

#if SQLITE_MAX_MMAP_SIZE>0
  if( rc==SQLITE_OK && oldMmapSize>0 ){
    if( oldMmapSize>nByte ){


      winMapfile(pFile, -1);
    }else{
      winMapfile(pFile, oldMmapSize);
    }
  }
#endif

  OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
           osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
  return rc;
}
Changes to src/shell.c.in.
75
76
77
78
79
80
81

82
83
84
85
86
87


88
89
90
91
92
93
94
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>
# endif
#endif
#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
# include <unistd.h>
# include <dirent.h>

# if defined(__MINGW32__)
#  define DIRENT dirent
#  ifndef S_ISLNK
#   define S_ISLNK(mode) (0)
#  endif
# endif


#endif
#include <sys/types.h>
#include <sys/stat.h>

#if HAVE_READLINE
# include <readline/readline.h>
# include <readline/history.h>







>






>
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
#  include <pwd.h>
# endif
#endif
#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
# include <unistd.h>
# include <dirent.h>
# define GETPID getpid
# if defined(__MINGW32__)
#  define DIRENT dirent
#  ifndef S_ISLNK
#   define S_ISLNK(mode) (0)
#  endif
# endif
#else
# define GETPID (int)GetCurrentProcessId
#endif
#include <sys/types.h>
#include <sys/stat.h>

#if HAVE_READLINE
# include <readline/readline.h>
# include <readline/history.h>
8343
8344
8345
8346
8347
8348
8349

















8350
8351
8352
8353
8354
8355
8356
  int argcToFree = 0;
#endif

  setBinaryMode(stdin, 0);
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
  stdin_is_interactive = isatty(0);
  stdout_is_console = isatty(1);


















#if USE_SYSTEM_SQLITE+0!=1
  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
            sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }







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







8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
  int argcToFree = 0;
#endif

  setBinaryMode(stdin, 0);
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
  stdin_is_interactive = isatty(0);
  stdout_is_console = isatty(1);

#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){
      fprintf(stderr,
          "attach debugger to process %d and press any key to continue.\n",
          GETPID());
      fgetc(stdin);
    }else{
#if defined(_WIN32) || defined(WIN32)
      DebugBreak();
#elif defined(SIGTRAP)
      raise(SIGTRAP);
#endif
    }
  }
#endif

#if USE_SYSTEM_SQLITE+0!=1
  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
            sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
  }
Changes to src/tclsqlite.c.
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71


72
73
74
75
76
77
78
# include <assert.h>
  typedef unsigned char u8;
#endif
#include <ctype.h>

/* Used to get the current process ID */
#if !defined(_WIN32)

# include <unistd.h>
# define GETPID getpid
#elif !defined(_WIN32_WCE)
# ifndef SQLITE_AMALGAMATION
#  ifndef WIN32_LEAN_AND_MEAN
#   define WIN32_LEAN_AND_MEAN
#  endif
#  include <windows.h>
# endif


# define GETPID (int)GetCurrentProcessId
#endif

/*
 * Windows needs to know which symbols to export.  Unix does not.
 * BUILD_sqlite should be undefined for Unix.
 */







>









>
>







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
# include <assert.h>
  typedef unsigned char u8;
#endif
#include <ctype.h>

/* Used to get the current process ID */
#if !defined(_WIN32)
# include <signal.h>
# include <unistd.h>
# define GETPID getpid
#elif !defined(_WIN32_WCE)
# ifndef SQLITE_AMALGAMATION
#  ifndef WIN32_LEAN_AND_MEAN
#   define WIN32_LEAN_AND_MEAN
#  endif
#  include <windows.h>
# endif
# include <io.h>
# define isatty(h) _isatty(h)
# define GETPID (int)GetCurrentProcessId
#endif

/*
 * Windows needs to know which symbols to export.  Unix does not.
 * BUILD_sqlite should be undefined for Unix.
 */
3729
3730
3731
3732
3733
3734
3735
3736

3737
3738
3739
3740







3741
3742
3743
3744
3745
3746
3747
  const char *zScript = 0;
  char zArgc[32];
#if defined(TCLSH_INIT_PROC)
  extern const char *TCLSH_INIT_PROC(Tcl_Interp*);
#endif

#if !defined(_WIN32_WCE)
  if( getenv("BREAK") ){

    fprintf(stderr,
        "attach debugger to process %d and press any key to continue.\n",
        GETPID());
    fgetc(stdin);







  }
#endif

  /* Call sqlite3_shutdown() once before doing anything else. This is to
  ** test that sqlite3_shutdown() can be safely called by a process before
  ** sqlite3_initialize() is. */
  sqlite3_shutdown();







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







3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
  const char *zScript = 0;
  char zArgc[32];
#if defined(TCLSH_INIT_PROC)
  extern const char *TCLSH_INIT_PROC(Tcl_Interp*);
#endif

#if !defined(_WIN32_WCE)
  if( getenv("SQLITE_DEBUG_BREAK") ){
    if( isatty(0) && isatty(2) ){
      fprintf(stderr,
          "attach debugger to process %d and press any key to continue.\n",
          GETPID());
      fgetc(stdin);
    }else{
#if defined(_WIN32) || defined(WIN32)
      DebugBreak();
#elif defined(SIGTRAP)
      raise(SIGTRAP);
#endif
    }
  }
#endif

  /* Call sqlite3_shutdown() once before doing anything else. This is to
  ** test that sqlite3_shutdown() can be safely called by a process before
  ** sqlite3_initialize() is. */
  sqlite3_shutdown();
Changes to test/mmap1.test.
272
273
274
275
276
277
278










































279
280
  sqlite3_column_text $::STMT 0
} $bbb

do_test 5.5 {
  sqlite3_finalize $::STMT
} SQLITE_OK












































finish_test







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


272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  sqlite3_column_text $::STMT 0
} $bbb

do_test 5.5 {
  sqlite3_finalize $::STMT
} SQLITE_OK

#
# The "6.*" tests are designed to test the interaction of mmap with file
# truncation (e.g. on Win32) via the VACUUM command.
#
forcedelete test2.db
sqlite3 db2 test2.db
do_test 6.0 {
  db2 eval {
    PRAGMA page_size = 4096;
  }
} {}
do_test 6.1 {
  db2 eval {
    CREATE TABLE t1(x);
    INSERT INTO t1(x) VALUES(randomblob(1000000));
  }
} {}
do_test 6.2 {
  db2 eval {
    PRAGMA mmap_size = 1048576;
  }
} {1048576}
do_test 6.3 {
  expr {[file size test2.db] > 1000000}
} {1}
do_test 6.4 {
  db2 eval {
    DELETE FROM t1;
  }
} {}
do_test 6.5 {
  expr {[file size test2.db] > 1000000}
} {1}
do_test 6.6 {
  db2 eval {
    VACUUM;
  }
} {}
do_test 6.7 {
  expr {[file size test2.db] < 1000000}
} {1}
db2 close

finish_test
Changes to test/permutations.test.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
if {$::tcl_platform(platform)!="unix"} {
  set alltests [test_set $alltests -exclude crash.test crash2.test]
}
set alltests [test_set $alltests -exclude {
  all.test        async.test         quick.test  veryquick.test
  memleak.test    permutations.test  soak.test   fts3.test
  mallocAll.test  rtree.test         full.test   extraquick.test
  session.test
}]

set allquicktests [test_set $alltests -exclude {
  async2.test async3.test backup_ioerr.test corrupt.test
  corruptC.test crash.test crash2.test crash3.test crash4.test crash5.test
  crash6.test crash7.test delete3.test e_fts3.test fts3rnd.test
  fkey_malloc.test fuzz.test fuzz3.test fuzz_malloc.test in2.test loadext.test







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
if {$::tcl_platform(platform)!="unix"} {
  set alltests [test_set $alltests -exclude crash.test crash2.test]
}
set alltests [test_set $alltests -exclude {
  all.test        async.test         quick.test  veryquick.test
  memleak.test    permutations.test  soak.test   fts3.test
  mallocAll.test  rtree.test         full.test   extraquick.test
  session.test    rbu.test
}]

set allquicktests [test_set $alltests -exclude {
  async2.test async3.test backup_ioerr.test corrupt.test
  corruptC.test crash.test crash2.test crash3.test crash4.test crash5.test
  crash6.test crash7.test delete3.test e_fts3.test fts3rnd.test
  fkey_malloc.test fuzz.test fuzz3.test fuzz_malloc.test in2.test loadext.test