/ Changes On Branch winNativeHeap
Login

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

Changes In Branch winNativeHeap Excluding Merge-Ins

This is equivalent to a diff from 988998fe7b to 5ed7633d41

2011-08-26
11:18
Merge Win32 native heap support into trunk. (check-in: 5238a74987 user: mistachkin tags: trunk)
05:40
In the MSVC makefile, allow symbols to be enabled without NDEBUG defined. Also, for the win32lock test, make sure the database is closed prior to shutdown. (Closed-Leaf check-in: 5ed7633d41 user: mistachkin tags: winNativeHeap)
01:45
Disable checking the winMemData structure signature when compiled with NDEBUG. (check-in: 50edc2f914 user: mistachkin tags: winNativeHeap)
2011-08-25
00:14
Add the SQLITE_EXTRA_INIT macro. (check-in: a3220f36c1 user: drh tags: trunk)
2011-08-24
16:13
Experimental work to allow SQLite to use the native Win32 heap API. (check-in: bf3d0ab538 user: mistachkin tags: winNativeHeap)
15:18
Updates to the sqlite3_mem_methods documentation. (check-in: 988998fe7b user: drh tags: trunk)
15:12
Fix some harmless compiler warnings. (check-in: 46f5a68bfa user: drh tags: trunk)

Changes to Makefile.msc.

1
2
3
4
5
6
7
8
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













45
46
47
48
49
50












51
52
53
54
55
56
57
#
# nmake Makefile for SQLite
#

# The toplevel directory of the source tree.  This is the directory
# that contains this "Makefile.msc".
#
TOP = .

# Set this non-0 to create and use the SQLite amalgamation file.
#
USE_AMALGAMATION = 1


















# Version numbers and release number for the SQLite being compiled.
#
VERSION = 3.7
VERSION_NUMBER = 3007007
RELEASE = 3.7.7

# C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
BCC = cl.exe -O2

# C Compile and options for use in building executables that
# will run on the target platform.  (BCC and TCC are usually the
# same unless your are cross-compiling.)
#
TCC = cl.exe -W3 -O2 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise

# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in 
# any extension header files by default.  For non-amalgamation
# builds, we need to make sure the compiler can find these.
#
!IF $(USE_AMALGAMATION)==0
TCC = $(TCC) -I$(TOP)\ext\fts3
TCC = $(TCC) -I$(TOP)\ext\rtree
!ENDIF

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#

TCC = $(TCC) -DNDEBUG














#
# Prevent warnings about "insecure" runtime library functions being used.
#
TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS













# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""












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










|





|














>

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






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







1
2
3
4
5
6
7
8
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
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
94
95
96
97
98
99
100
#
# nmake Makefile for SQLite
#

# The toplevel directory of the source tree.  This is the directory
# that contains this "Makefile.msc".
#
TOP = .

# Set this non-0 to create and use the SQLite amalgamation file.
#
USE_AMALGAMATION = 1

# Set this to non-0 to create and use PDBs.
#
SYMBOLS = 1

# Set this to one of the following values to enable various debugging
# features.  Each level includes the debugging options from the previous
# levels.  Currently, the recognized values for DEBUG are:
#
# 0 == NDEBUG: Disables assert() and other runtime diagnostics.
# 1 == Disables NDEBUG and all optimizations and then enables PDBs.
# 2 == SQLITE_DEBUG: Enables various diagnostics messages and code.
# 3 == SQLITE_WIN32_MALLOC_VALIDATE: Validate the Win32 native heap per call.
# 4 == SQLITE_DEBUG_OS_TRACE: Enables output from the OSTRACE() macros.
# 5 == SQLITE_ENABLE_IOTRACE: Enables output from the IOTRACE() macros.
#
DEBUG = 0

# Version numbers and release number for the SQLite being compiled.
#
VERSION = 3.7
VERSION_NUMBER = 3007007
RELEASE = 3.7.7

# C Compiler and options for use in building executables that
# will run on the platform that is doing the build.
#
BCC = cl.exe

# C Compile and options for use in building executables that
# will run on the target platform.  (BCC and TCC are usually the
# same unless your are cross-compiling.)
#
TCC = cl.exe -W3 -DSQLITE_OS_WIN=1 -I. -I$(TOP)\src -fp:precise

# The mksqlite3c.tcl and mksqlite3h.tcl scripts will pull in 
# any extension header files by default.  For non-amalgamation
# builds, we need to make sure the compiler can find these.
#
!IF $(USE_AMALGAMATION)==0
TCC = $(TCC) -I$(TOP)\ext\fts3
TCC = $(TCC) -I$(TOP)\ext\rtree
!ENDIF

# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
#
!IF $(DEBUG)==0
TCC = $(TCC) -DNDEBUG
!ENDIF

!IF $(DEBUG)>1
TCC = $(TCC) -DSQLITE_DEBUG
!ENDIF

!IF $(DEBUG)>3
TCC = $(TCC) -DSQLITE_DEBUG_OS_TRACE=1
!ENDIF

!IF $(DEBUG)>4
TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF

#
# Prevent warnings about "insecure" runtime library functions being used.
#
TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS

#
# Use native Win32 heap instead of malloc/free?
#
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1

#
# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF

# The locations of the Tcl header and library files.  Also, the library that
# non-stubs enabled programs using Tcl must link against.  These variables
# (TCLINCDIR, TCLLIBDIR, and LIBTCL) may be overridden via the environment
# prior to running nmake in order to match the actual installed location and
# version on this machine.
#
!if "$(TCLINCDIR)" == ""
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
# END required Windows option

TCC = $(TCC) $(OPT_FEATURE_FLAGS)

# Add in any optional parameters specified on the make commane line
# ie.  make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
TCC = $(TCC) $(OPTS)













# libtool compile/link
LTCOMPILE = $(TCC) -Fo$@
LTLIB = lib.exe
LTLINK = $(TCC) -Fe$@

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IF "$(PLATFORM)"!=""
LTLINKOPTS = /MACHINE:$(PLATFORM)
LTLIBOPTS = /MACHINE:$(PLATFORM)
!ENDIF






# nawk compatible awk.
NAWK = gawk.exe

# You should not have to change anything below this line
###############################################################################








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














>
>
>
>
>







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# END required Windows option

TCC = $(TCC) $(OPT_FEATURE_FLAGS)

# Add in any optional parameters specified on the make commane line
# ie.  make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
TCC = $(TCC) $(OPTS)

# If symbols are enabled, enable PDBs.
# If debugging is enabled, disable all optimizations and enable PDBs.
!IF $(DEBUG)>0
TCC = $(TCC) -Od -D_DEBUG
!ELSE
TCC = $(TCC) -O2
!ENDIF

!IF $(DEBUG)>0 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
!ENDIF

# libtool compile/link
LTCOMPILE = $(TCC) -Fo$@
LTLIB = lib.exe
LTLINK = $(TCC) -Fe$@

# If a platform was set, force the linker to target that.
# Note that the vcvars*.bat family of batch files typically
# set this for you.  Otherwise, the linker will attempt
# to deduce the binary type based on the object files.
!IF "$(PLATFORM)"!=""
LTLINKOPTS = /MACHINE:$(PLATFORM)
LTLIBOPTS = /MACHINE:$(PLATFORM)
!ENDIF

# If debugging is enabled, enable PDBs.
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
LTLINKOPTS = $(LTLINKOPTS) /DEBUG
!ENDIF

# nawk compatible awk.
NAWK = gawk.exe

# You should not have to change anything below this line
###############################################################################

Changes to src/os_win.c.

115
116
117
118
119
120
121






































































122
123
124
125
126
127
128
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif
};








































































/*
** Forward prototypes.
*/
static int getSectorSize(
    sqlite3_vfs *pVfs,
    const char *zRelative     /* UTF-8 file name */







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







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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  HANDLE hMutex;          /* Mutex used to control access to shared lock */  
  HANDLE hShared;         /* Shared memory segment used for locking */
  winceLock local;        /* Locks obtained by this instance of winFile */
  winceLock *shared;      /* Global shared lock memory for the file  */
#endif
};

/*
 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
 * various Win32 API heap functions instead of our own.
 */
#ifdef SQLITE_WIN32_MALLOC
/*
 * The initial size of the Win32-specific heap.  This value may be zero.
 */
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
#  define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
                                       (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
#endif

/*
 * The maximum size of the Win32-specific heap.  This value may be zero.
 */
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
#  define SQLITE_WIN32_HEAP_MAX_SIZE  (0)
#endif

/*
 * The extra flags to use in calls to the Win32 heap APIs.  This value may be
 * zero for the default behavior.
 */
#ifndef SQLITE_WIN32_HEAP_FLAGS
#  define SQLITE_WIN32_HEAP_FLAGS     (0)
#endif

/*
** The winMemData structure stores information required by the Win32-specific
** sqlite3_mem_methods implementation.
*/
typedef struct winMemData winMemData;
struct winMemData {
#ifndef NDEBUG
  u32 magic;    /* Magic number to detect structure corruption. */
#endif
  HANDLE hHeap; /* The handle to our heap. */
  BOOL bOwned;  /* Do we own the heap (i.e. destroy it on shutdown)? */
};

#ifndef NDEBUG
#define WINMEM_MAGIC     0x42b2830b
#endif

static struct winMemData win_mem_data = {
#ifndef NDEBUG
  WINMEM_MAGIC,
#endif
  NULL, FALSE
};

#ifndef NDEBUG
#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
#else
#define winMemAssertMagic()
#endif

#define winMemGetHeap() win_mem_data.hHeap

static void *winMemMalloc(int nBytes);
static void winMemFree(void *pPrior);
static void *winMemRealloc(void *pPrior, int nBytes);
static int winMemSize(void *p);
static int winMemRoundup(int n);
static int winMemInit(void *pAppData);
static void winMemShutdown(void *pAppData);

const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */

/*
** Forward prototypes.
*/
static int getSectorSize(
    sqlite3_vfs *pVfs,
    const char *zRelative     /* UTF-8 file name */
167
168
169
170
171
172
173






















































































































































































174
175
176
177
178
179
180
      GetVersionEx(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
  }
#endif /* SQLITE_OS_WINCE */























































































































































































/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
  int nChar;







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







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
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
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
      GetVersionEx(&sInfo);
      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return sqlite3_os_type==2;
  }
#endif /* SQLITE_OS_WINCE */

#ifdef SQLITE_WIN32_MALLOC
/*
** Allocate nBytes of memory.
*/
static void *winMemMalloc(int nBytes){
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  assert( nBytes>=0 );
  p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  if( !p ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
        nBytes, GetLastError(), (void*)hHeap);
  }
  return p;
}

/*
** Free memory.
*/
static void winMemFree(void *pPrior){
  HANDLE hHeap;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
  if( !HeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
        pPrior, GetLastError(), (void*)hHeap);
  }
}

/*
** Change the size of an existing memory allocation
*/
static void *winMemRealloc(void *pPrior, int nBytes){
  HANDLE hHeap;
  void *p;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
  assert( nBytes>=0 );
  if( !pPrior ){
    p = HeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
  }else{
    p = HeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
  }
  if( !p ){
    sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
        pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, GetLastError(),
        (void*)hHeap);
  }
  return p;
}

/*
** Return the size of an outstanding allocation, in bytes.
*/
static int winMemSize(void *p){
  HANDLE hHeap;
  SIZE_T n;

  winMemAssertMagic();
  hHeap = winMemGetHeap();
  assert( hHeap!=0 );
  assert( hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert ( HeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  if( !p ) return 0;
  n = HeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
  if( n==(SIZE_T)-1 ){
    sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
        p, GetLastError(), (void*)hHeap);
    return 0;
  }
  return (int)n;
}

/*
** Round up a request size to the next valid allocation size.
*/
static int winMemRoundup(int n){
  return n;
}

/*
** Initialize this module.
*/
static int winMemInit(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return SQLITE_ERROR;
  assert( pWinMemData->magic==WINMEM_MAGIC );
  if( !pWinMemData->hHeap ){
    pWinMemData->hHeap = HeapCreate(SQLITE_WIN32_HEAP_FLAGS,
                                    SQLITE_WIN32_HEAP_INIT_SIZE,
                                    SQLITE_WIN32_HEAP_MAX_SIZE);
    if( !pWinMemData->hHeap ){
      sqlite3_log(SQLITE_NOMEM,
          "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
          GetLastError(), SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE,
          SQLITE_WIN32_HEAP_MAX_SIZE);
      return SQLITE_NOMEM;
    }
    pWinMemData->bOwned = TRUE;
  }
  assert( pWinMemData->hHeap!=0 );
  assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
  assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
  return SQLITE_OK;
}

/*
** Deinitialize this module.
*/
static void winMemShutdown(void *pAppData){
  winMemData *pWinMemData = (winMemData *)pAppData;

  if( !pWinMemData ) return;
  if( pWinMemData->hHeap ){
    assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#ifdef SQLITE_WIN32_MALLOC_VALIDATE
    assert( HeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
    if( pWinMemData->bOwned ){
      if( !HeapDestroy(pWinMemData->hHeap) ){
        sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
            GetLastError(), (void*)pWinMemData->hHeap);
      }
      pWinMemData->bOwned = FALSE;
    }
    pWinMemData->hHeap = NULL;
  }
}

/*
** Populate the low-level memory allocation function pointers in
** sqlite3GlobalConfig.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite3_config(), and therefore
** is not required to be threadsafe (it is not).
*/
const sqlite3_mem_methods *sqlite3MemGetWin32(void){
  static const sqlite3_mem_methods winMemMethods = {
    winMemMalloc,
    winMemFree,
    winMemRealloc,
    winMemSize,
    winMemRoundup,
    winMemInit,
    winMemShutdown,
    &win_mem_data
  };
  return &winMemMethods;
}

void sqlite3MemSetDefault(void){
  sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
}
#endif /* SQLITE_WIN32_MALLOC */

/*
** Convert a UTF-8 string to microsoft unicode (UTF-16?). 
**
** Space to hold the returned string is obtained from malloc.
*/
static WCHAR *utf8ToUnicode(const char *zFilename){
  int nChar;
1347
1348
1349
1350
1351
1352
1353

1354




1355
1356
1357


1358
1359
1360
1361
1362
1363
1364
1365
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {

      sqlite3_int64 sz = *(sqlite3_int64*)pArg;




      SimulateIOErrorBenign(1);
      winTruncate(id, sz);
      SimulateIOErrorBenign(0);


      return SQLITE_OK;
    }
    case SQLITE_FCNTL_PERSIST_WAL: {
      int bPersist = *(int*)pArg;
      if( bPersist<0 ){
        *(int*)pArg = pFile->bPersistWal;
      }else{
        pFile->bPersistWal = bPersist!=0;







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







1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_CHUNK_SIZE: {
      pFile->szChunk = *(int *)pArg;
      return SQLITE_OK;
    }
    case SQLITE_FCNTL_SIZE_HINT: {
      winFile *pFile = (winFile*)id;
      sqlite3_int64 oldSz;
      int rc = winFileSize(id, &oldSz);
      if( rc==SQLITE_OK ){
        sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
        if( newSz>oldSz ){
          SimulateIOErrorBenign(1);
          rc = winTruncate(id, newSz);
          SimulateIOErrorBenign(0);
        }
      }
      return rc;
    }
    case SQLITE_FCNTL_PERSIST_WAL: {
      int bPersist = *(int*)pArg;
      if( bPersist<0 ){
        *(int*)pArg = pFile->bPersistWal;
      }else{
        pFile->bPersistWal = bPersist!=0;

Changes to src/sqliteInt.h.

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
#endif

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()

**     SQLITE_MEMDEBUG               // Debugging version of system malloc()





**
** (Historical note:  There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/







>

>
>
>
>
>







|



|







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
#endif

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE_SYSTEM_MALLOC          // Use normal system malloc()
**     SQLITE_WIN32_MALLOC           // Use Win32 native heap API
**     SQLITE_MEMDEBUG               // Debugging version of system malloc()
**
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
** assert() macro is enabled, each call into the Win32 native heap subsystem
** will cause HeapValidate to be called.  If heap validation should fail, an
** assertion will be triggered.
**
** (Historical note:  There used to be several other options, but we've
** pared it down to just these two.)
**
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
 is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG"
#endif
#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/

Changes to test/pager1.test.

2414
2415
2416
2417
2418
2419
2420





































2421
2422
  
  hexio_write test.db2-journal 24 00000000
  sqlite3 db2 test.db2
  execsql { PRAGMA integrity_check } db2
} {ok}
}







































finish_test







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


2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
  
  hexio_write test.db2-journal 24 00000000
  sqlite3 db2 test.db2
  execsql { PRAGMA integrity_check } db2
} {ok}
}

#-------------------------------------------------------------------------
# Test that a database file can be "pre-hinted" to a certain size and that
# subsequent spilling of the pager cache does not result in the database
# file being shrunk.
#
catch {db close}
forcedelete test.db

do_test pager1-32.1 {
  sqlite3 db test.db
  execsql {
    CREATE TABLE t1(x, y);
  }
  db close
  sqlite3 db test.db
  execsql {
    BEGIN;
    INSERT INTO t1 VALUES(1, randomblob(10000));
  }
  file_control_sizehint_test db main 20971520; # 20MB
  execsql {
    PRAGMA cache_size = 10;
    INSERT INTO t1 VALUES(1, randomblob(10000));
    INSERT INTO t1 VALUES(2, randomblob(10000));
    INSERT INTO t1 SELECT x+2, randomblob(10000) from t1;
    INSERT INTO t1 SELECT x+4, randomblob(10000) from t1;
    INSERT INTO t1 SELECT x+8, randomblob(10000) from t1;
    INSERT INTO t1 SELECT x+16, randomblob(10000) from t1;
    SELECT count(*) FROM t1;
    COMMIT;
  }
  db close
  file size test.db
} {20971520}

# Cleanup 20MB file left by the previous test.
forcedelete test.db

finish_test

Changes to test/win32lock.test.

65
66
67
68
69
70
71




72
73
74
75
76
77
78
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 25




  sqlite3_sleep 10
}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {







>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 25
  if {$delay1 > 12500} {
    puts "Timed out waiting for \"ok\" and \"error\" results."
    break
  }
  sqlite3_sleep 10
}

do_test win32lock-2.0 {
  file_control_win32_av_retry db -1 -1
} {0 10 25}
do_test win32lock-2.1 {
109
110
111
112
113
114
115




116
117
118
119
120

121
122
123
124
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 1




  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte

sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test







>
>
>
>





>




113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
        regsub {\d+} $::log # x
        set x
      } {{delayed #ms for lock/sharing conflict}}
    }
  }
  if {[llength $win32_lock_ok] && [llength $win32_lock_error]} break
  incr delay1 1
  if {$delay1 > 500} {
    puts "Timed out waiting for \"ok\" and \"error\" results."
    break
  }
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close
sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test