Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(935)

Side by Side Diff: third_party/sqlite/sqlite-src-3080704/src/test_vfs.c

Issue 883353008: [sql] Import reference version of SQLite 3.8.7.4. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Hold back encoding change which is messing up patch. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 ** 2010 May 05 2 ** 2010 May 05
3 ** 3 **
4 ** The author disclaims copyright to this source code. In place of 4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing: 5 ** a legal notice, here is a blessing:
6 ** 6 **
7 ** May you do good and not evil. 7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others. 8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give. 9 ** May you share freely, never taking more than you give.
10 ** 10 **
11 ****************************************************************************** 11 ******************************************************************************
12 ** 12 **
13 */
14 #if SQLITE_TEST /* This file is used for testing only */
15
16 /*
17 ** This file contains the implementation of the Tcl [testvfs] command, 13 ** This file contains the implementation of the Tcl [testvfs] command,
18 ** used to create SQLite VFS implementations with various properties and 14 ** used to create SQLite VFS implementations with various properties and
19 ** instrumentation to support testing SQLite. 15 ** instrumentation to support testing SQLite.
20 ** 16 **
21 ** testvfs VFSNAME ?OPTIONS? 17 ** testvfs VFSNAME ?OPTIONS?
22 ** 18 **
23 ** Available options are: 19 ** Available options are:
24 ** 20 **
25 ** -noshm BOOLEAN (True to omit shm methods. Default false) 21 ** -noshm BOOLEAN (True to omit shm methods. Default false)
26 ** -default BOOLEAN (True to make the vfs default. Default false) 22 ** -default BOOLEAN (True to make the vfs default. Default false)
27 ** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile) 23 ** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile)
28 ** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname) 24 ** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname)
29 ** -iversion INTEGER (Value for sqlite3_vfs.iVersion) 25 ** -iversion INTEGER (Value for sqlite3_vfs.iVersion)
30 */ 26 */
27 #if SQLITE_TEST /* This file is used for testing only */
31 28
32 #include "sqlite3.h" 29 #include "sqlite3.h"
33 #include "sqliteInt.h" 30 #include "sqliteInt.h"
31 #include <tcl.h>
34 32
35 typedef struct Testvfs Testvfs; 33 typedef struct Testvfs Testvfs;
36 typedef struct TestvfsShm TestvfsShm; 34 typedef struct TestvfsShm TestvfsShm;
37 typedef struct TestvfsBuffer TestvfsBuffer; 35 typedef struct TestvfsBuffer TestvfsBuffer;
38 typedef struct TestvfsFile TestvfsFile; 36 typedef struct TestvfsFile TestvfsFile;
39 typedef struct TestvfsFd TestvfsFd; 37 typedef struct TestvfsFd TestvfsFd;
40 38
41 /* 39 /*
42 ** An open file handle. 40 ** An open file handle.
43 */ 41 */
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 ** An instance of this structure is allocated for each VFS created. The 73 ** An instance of this structure is allocated for each VFS created. The
76 ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite 74 ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
77 ** is set to point to it. 75 ** is set to point to it.
78 */ 76 */
79 struct Testvfs { 77 struct Testvfs {
80 char *zName; /* Name of this VFS */ 78 char *zName; /* Name of this VFS */
81 sqlite3_vfs *pParent; /* The VFS to use for file IO */ 79 sqlite3_vfs *pParent; /* The VFS to use for file IO */
82 sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ 80 sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */
83 Tcl_Interp *interp; /* Interpreter to run script in */ 81 Tcl_Interp *interp; /* Interpreter to run script in */
84 Tcl_Obj *pScript; /* Script to execute */ 82 Tcl_Obj *pScript; /* Script to execute */
85 int nScript; /* Number of elements in array apScript */
86 Tcl_Obj **apScript; /* Array version of pScript */
87 TestvfsBuffer *pBuffer; /* List of shared buffers */ 83 TestvfsBuffer *pBuffer; /* List of shared buffers */
88 int isNoshm; 84 int isNoshm;
85 int isFullshm;
89 86
90 int mask; /* Mask controlling [script] and [ioerr] */ 87 int mask; /* Mask controlling [script] and [ioerr] */
91 88
92 TestFaultInject ioerr_err; 89 TestFaultInject ioerr_err;
93 TestFaultInject full_err; 90 TestFaultInject full_err;
94 TestFaultInject cantopen_err; 91 TestFaultInject cantopen_err;
95 92
96 #if 0 93 #if 0
97 int iIoerrCnt; 94 int iIoerrCnt;
98 int ioerr; 95 int ioerr;
99 int nIoerrFail; 96 int nIoerrFail;
100 int iFullCnt; 97 int iFullCnt;
101 int fullerr; 98 int fullerr;
102 int nFullFail; 99 int nFullFail;
103 #endif 100 #endif
104 101
105 int iDevchar; 102 int iDevchar;
106 int iSectorsize; 103 int iSectorsize;
107 }; 104 };
108 105
109 /* 106 /*
110 ** The Testvfs.mask variable is set to a combination of the following. 107 ** The Testvfs.mask variable is set to a combination of the following.
111 ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the 108 ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the
112 ** corresponding VFS method is ignored for purposes of: 109 ** corresponding VFS method is ignored for purposes of:
113 ** 110 **
114 ** + Simulating IO errors, and 111 ** + Simulating IO errors, and
115 ** + Invoking the Tcl callback script. 112 ** + Invoking the Tcl callback script.
116 */ 113 */
117 #define TESTVFS_SHMOPEN_MASK 0x00000001 114 #define TESTVFS_SHMOPEN_MASK 0x00000001
118 #define TESTVFS_SHMLOCK_MASK 0x00000010 115 #define TESTVFS_SHMLOCK_MASK 0x00000010
119 #define TESTVFS_SHMMAP_MASK 0x00000020 116 #define TESTVFS_SHMMAP_MASK 0x00000020
120 #define TESTVFS_SHMBARRIER_MASK 0x00000040 117 #define TESTVFS_SHMBARRIER_MASK 0x00000040
121 #define TESTVFS_SHMCLOSE_MASK 0x00000080 118 #define TESTVFS_SHMCLOSE_MASK 0x00000080
122 119
123 #define TESTVFS_OPEN_MASK 0x00000100 120 #define TESTVFS_OPEN_MASK 0x00000100
124 #define TESTVFS_SYNC_MASK 0x00000200 121 #define TESTVFS_SYNC_MASK 0x00000200
125 #define TESTVFS_DELETE_MASK 0x00000400 122 #define TESTVFS_DELETE_MASK 0x00000400
126 #define TESTVFS_CLOSE_MASK 0x00000800 123 #define TESTVFS_CLOSE_MASK 0x00000800
127 #define TESTVFS_WRITE_MASK 0x00001000 124 #define TESTVFS_WRITE_MASK 0x00001000
128 #define TESTVFS_TRUNCATE_MASK 0x00002000 125 #define TESTVFS_TRUNCATE_MASK 0x00002000
129 #define TESTVFS_ACCESS_MASK 0x00004000 126 #define TESTVFS_ACCESS_MASK 0x00004000
130 #define TESTVFS_ALL_MASK 0x00007FFF 127 #define TESTVFS_FULLPATHNAME_MASK 0x00008000
128 #define TESTVFS_READ_MASK 0x00010000
129 #define TESTVFS_UNLOCK_MASK 0x00020000
130 #define TESTVFS_LOCK_MASK 0x00040000
131 #define TESTVFS_CKLOCK_MASK 0x00080000
132
133 #define TESTVFS_ALL_MASK 0x000FFFFF
131 134
132 135
133 #define TESTVFS_MAX_PAGES 1024 136 #define TESTVFS_MAX_PAGES 1024
134 137
135 /* 138 /*
136 ** A shared-memory buffer. There is one of these objects for each shared 139 ** A shared-memory buffer. There is one of these objects for each shared
137 ** memory region opened by clients. If two clients open the same file, 140 ** memory region opened by clients. If two clients open the same file,
138 ** there are two TestvfsFile structures but only one TestvfsBuffer structure. 141 ** there are two TestvfsFile structures but only one TestvfsBuffer structure.
139 */ 142 */
140 struct TestvfsBuffer { 143 struct TestvfsBuffer {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); 186 static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
184 static int tvfsSleep(sqlite3_vfs*, int microseconds); 187 static int tvfsSleep(sqlite3_vfs*, int microseconds);
185 static int tvfsCurrentTime(sqlite3_vfs*, double*); 188 static int tvfsCurrentTime(sqlite3_vfs*, double*);
186 189
187 static int tvfsShmOpen(sqlite3_file*); 190 static int tvfsShmOpen(sqlite3_file*);
188 static int tvfsShmLock(sqlite3_file*, int , int, int); 191 static int tvfsShmLock(sqlite3_file*, int , int, int);
189 static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **); 192 static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **);
190 static void tvfsShmBarrier(sqlite3_file*); 193 static void tvfsShmBarrier(sqlite3_file*);
191 static int tvfsShmUnmap(sqlite3_file*, int); 194 static int tvfsShmUnmap(sqlite3_file*, int);
192 195
196 static int tvfsFetch(sqlite3_file*, sqlite3_int64, int, void**);
197 static int tvfsUnfetch(sqlite3_file*, sqlite3_int64, void*);
198
193 static sqlite3_io_methods tvfs_io_methods = { 199 static sqlite3_io_methods tvfs_io_methods = {
194 2, /* iVersion */ 200 3, /* iVersion */
195 tvfsClose, /* xClose */ 201 tvfsClose, /* xClose */
196 tvfsRead, /* xRead */ 202 tvfsRead, /* xRead */
197 tvfsWrite, /* xWrite */ 203 tvfsWrite, /* xWrite */
198 tvfsTruncate, /* xTruncate */ 204 tvfsTruncate, /* xTruncate */
199 tvfsSync, /* xSync */ 205 tvfsSync, /* xSync */
200 tvfsFileSize, /* xFileSize */ 206 tvfsFileSize, /* xFileSize */
201 tvfsLock, /* xLock */ 207 tvfsLock, /* xLock */
202 tvfsUnlock, /* xUnlock */ 208 tvfsUnlock, /* xUnlock */
203 tvfsCheckReservedLock, /* xCheckReservedLock */ 209 tvfsCheckReservedLock, /* xCheckReservedLock */
204 tvfsFileControl, /* xFileControl */ 210 tvfsFileControl, /* xFileControl */
205 tvfsSectorSize, /* xSectorSize */ 211 tvfsSectorSize, /* xSectorSize */
206 tvfsDeviceCharacteristics, /* xDeviceCharacteristics */ 212 tvfsDeviceCharacteristics, /* xDeviceCharacteristics */
207 tvfsShmMap, /* xShmMap */ 213 tvfsShmMap, /* xShmMap */
208 tvfsShmLock, /* xShmLock */ 214 tvfsShmLock, /* xShmLock */
209 tvfsShmBarrier, /* xShmBarrier */ 215 tvfsShmBarrier, /* xShmBarrier */
210 tvfsShmUnmap /* xShmUnmap */ 216 tvfsShmUnmap, /* xShmUnmap */
217 tvfsFetch,
218 tvfsUnfetch
211 }; 219 };
212 220
213 static int tvfsResultCode(Testvfs *p, int *pRc){ 221 static int tvfsResultCode(Testvfs *p, int *pRc){
214 struct errcode { 222 struct errcode {
215 int eCode; 223 int eCode;
216 const char *zCode; 224 const char *zCode;
217 } aCode[] = { 225 } aCode[] = {
218 { SQLITE_OK, "SQLITE_OK" }, 226 { SQLITE_OK, "SQLITE_OK" },
219 { SQLITE_ERROR, "SQLITE_ERROR" }, 227 { SQLITE_ERROR, "SQLITE_ERROR" },
220 { SQLITE_IOERR, "SQLITE_IOERR" }, 228 { SQLITE_IOERR, "SQLITE_IOERR" },
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 static int tvfsInjectCantopenerr(Testvfs *p){ 267 static int tvfsInjectCantopenerr(Testvfs *p){
260 return tvfsInjectFault(&p->cantopen_err); 268 return tvfsInjectFault(&p->cantopen_err);
261 } 269 }
262 270
263 271
264 static void tvfsExecTcl( 272 static void tvfsExecTcl(
265 Testvfs *p, 273 Testvfs *p,
266 const char *zMethod, 274 const char *zMethod,
267 Tcl_Obj *arg1, 275 Tcl_Obj *arg1,
268 Tcl_Obj *arg2, 276 Tcl_Obj *arg2,
269 Tcl_Obj *arg3 277 Tcl_Obj *arg3,
278 Tcl_Obj *arg4
270 ){ 279 ){
271 int rc; /* Return code from Tcl_EvalObj() */ 280 int rc; /* Return code from Tcl_EvalObj() */
272 int nArg; /* Elements in eval'd list */ 281 Tcl_Obj *pEval;
273 int nScript;
274 Tcl_Obj ** ap;
275
276 assert( p->pScript ); 282 assert( p->pScript );
277 283
278 if( !p->apScript ){ 284 assert( zMethod );
279 int nByte; 285 assert( p );
280 int i; 286 assert( arg2==0 || arg1!=0 );
281 if( TCL_OK!=Tcl_ListObjGetElements(p->interp, p->pScript, &nScript, &ap) ){ 287 assert( arg3==0 || arg2!=0 );
282 Tcl_BackgroundError(p->interp);
283 Tcl_ResetResult(p->interp);
284 return;
285 }
286 p->nScript = nScript;
287 nByte = (nScript+TESTVFS_MAX_ARGS)*sizeof(Tcl_Obj *);
288 p->apScript = (Tcl_Obj **)ckalloc(nByte);
289 memset(p->apScript, 0, nByte);
290 for(i=0; i<nScript; i++){
291 p->apScript[i] = ap[i];
292 }
293 }
294 288
295 p->apScript[p->nScript] = Tcl_NewStringObj(zMethod, -1); 289 pEval = Tcl_DuplicateObj(p->pScript);
296 p->apScript[p->nScript+1] = arg1; 290 Tcl_IncrRefCount(p->pScript);
297 p->apScript[p->nScript+2] = arg2; 291 Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1));
298 p->apScript[p->nScript+3] = arg3; 292 if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1);
293 if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2);
294 if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3);
295 if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4);
299 296
300 for(nArg=p->nScript; p->apScript[nArg]; nArg++){ 297 rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
301 Tcl_IncrRefCount(p->apScript[nArg]);
302 }
303
304 rc = Tcl_EvalObjv(p->interp, nArg, p->apScript, TCL_EVAL_GLOBAL);
305 if( rc!=TCL_OK ){ 298 if( rc!=TCL_OK ){
306 Tcl_BackgroundError(p->interp); 299 Tcl_BackgroundError(p->interp);
307 Tcl_ResetResult(p->interp); 300 Tcl_ResetResult(p->interp);
308 } 301 }
309
310 for(nArg=p->nScript; p->apScript[nArg]; nArg++){
311 Tcl_DecrRefCount(p->apScript[nArg]);
312 p->apScript[nArg] = 0;
313 }
314 } 302 }
315 303
316 304
317 /* 305 /*
318 ** Close an tvfs-file. 306 ** Close an tvfs-file.
319 */ 307 */
320 static int tvfsClose(sqlite3_file *pFile){ 308 static int tvfsClose(sqlite3_file *pFile){
321 int rc; 309 int rc;
322 TestvfsFile *pTestfile = (TestvfsFile *)pFile; 310 TestvfsFile *pTestfile = (TestvfsFile *)pFile;
323 TestvfsFd *pFd = pTestfile->pFd; 311 TestvfsFd *pFd = pTestfile->pFd;
324 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 312 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
325 313
326 if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ 314 if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
327 tvfsExecTcl(p, "xClose", 315 tvfsExecTcl(p, "xClose",
328 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 316 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
329 ); 317 );
330 } 318 }
331 319
332 if( pFd->pShmId ){ 320 if( pFd->pShmId ){
333 Tcl_DecrRefCount(pFd->pShmId); 321 Tcl_DecrRefCount(pFd->pShmId);
334 pFd->pShmId = 0; 322 pFd->pShmId = 0;
335 } 323 }
336 if( pFile->pMethods ){ 324 if( pFile->pMethods ){
337 ckfree((char *)pFile->pMethods); 325 ckfree((char *)pFile->pMethods);
338 } 326 }
339 rc = sqlite3OsClose(pFd->pReal); 327 rc = sqlite3OsClose(pFd->pReal);
340 ckfree((char *)pFd); 328 ckfree((char *)pFd);
341 pTestfile->pFd = 0; 329 pTestfile->pFd = 0;
342 return rc; 330 return rc;
343 } 331 }
344 332
345 /* 333 /*
346 ** Read data from an tvfs-file. 334 ** Read data from an tvfs-file.
347 */ 335 */
348 static int tvfsRead( 336 static int tvfsRead(
349 sqlite3_file *pFile, 337 sqlite3_file *pFile,
350 void *zBuf, 338 void *zBuf,
351 int iAmt, 339 int iAmt,
352 sqlite_int64 iOfst 340 sqlite_int64 iOfst
353 ){ 341 ){
354 TestvfsFd *p = tvfsGetFd(pFile); 342 int rc = SQLITE_OK;
355 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); 343 TestvfsFd *pFd = tvfsGetFd(pFile);
344 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
345 if( p->pScript && p->mask&TESTVFS_READ_MASK ){
346 tvfsExecTcl(p, "xRead",
347 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
348 );
349 tvfsResultCode(p, &rc);
350 }
351 if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){
352 rc = SQLITE_IOERR;
353 }
354 if( rc==SQLITE_OK ){
355 rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst);
356 }
357 return rc;
356 } 358 }
357 359
358 /* 360 /*
359 ** Write data to an tvfs-file. 361 ** Write data to an tvfs-file.
360 */ 362 */
361 static int tvfsWrite( 363 static int tvfsWrite(
362 sqlite3_file *pFile, 364 sqlite3_file *pFile,
363 const void *zBuf, 365 const void *zBuf,
364 int iAmt, 366 int iAmt,
365 sqlite_int64 iOfst 367 sqlite_int64 iOfst
366 ){ 368 ){
367 int rc = SQLITE_OK; 369 int rc = SQLITE_OK;
368 TestvfsFd *pFd = tvfsGetFd(pFile); 370 TestvfsFd *pFd = tvfsGetFd(pFile);
369 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 371 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
370 372
371 if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ 373 if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
372 tvfsExecTcl(p, "xWrite", 374 tvfsExecTcl(p, "xWrite",
373 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 375 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
376 Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt)
374 ); 377 );
375 tvfsResultCode(p, &rc); 378 tvfsResultCode(p, &rc);
376 } 379 }
377 380
378 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){ 381 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
379 rc = SQLITE_FULL; 382 rc = SQLITE_FULL;
380 } 383 }
381 if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){ 384 if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
382 rc = SQLITE_IOERR; 385 rc = SQLITE_IOERR;
383 } 386 }
384 387
385 if( rc==SQLITE_OK ){ 388 if( rc==SQLITE_OK ){
386 rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst); 389 rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst);
387 } 390 }
388 return rc; 391 return rc;
389 } 392 }
390 393
391 /* 394 /*
392 ** Truncate an tvfs-file. 395 ** Truncate an tvfs-file.
393 */ 396 */
394 static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ 397 static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
395 int rc = SQLITE_OK; 398 int rc = SQLITE_OK;
396 TestvfsFd *pFd = tvfsGetFd(pFile); 399 TestvfsFd *pFd = tvfsGetFd(pFile);
397 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 400 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
398 401
399 if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ 402 if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
400 tvfsExecTcl(p, "xTruncate", 403 tvfsExecTcl(p, "xTruncate",
401 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 404 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0
402 ); 405 );
403 tvfsResultCode(p, &rc); 406 tvfsResultCode(p, &rc);
404 } 407 }
405 408
406 if( rc==SQLITE_OK ){ 409 if( rc==SQLITE_OK ){
407 rc = sqlite3OsTruncate(pFd->pReal, size); 410 rc = sqlite3OsTruncate(pFd->pReal, size);
408 } 411 }
409 return rc; 412 return rc;
410 } 413 }
411 414
(...skipping 20 matching lines...) Expand all
432 break; 435 break;
433 case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY: 436 case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY:
434 zFlags = "full|dataonly"; 437 zFlags = "full|dataonly";
435 break; 438 break;
436 default: 439 default:
437 assert(0); 440 assert(0);
438 } 441 }
439 442
440 tvfsExecTcl(p, "xSync", 443 tvfsExecTcl(p, "xSync",
441 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 444 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
442 Tcl_NewStringObj(zFlags, -1) 445 Tcl_NewStringObj(zFlags, -1), 0
443 ); 446 );
444 tvfsResultCode(p, &rc); 447 tvfsResultCode(p, &rc);
445 } 448 }
446 449
447 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; 450 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL;
448 451
449 if( rc==SQLITE_OK ){ 452 if( rc==SQLITE_OK ){
450 rc = sqlite3OsSync(pFd->pReal, flags); 453 rc = sqlite3OsSync(pFd->pReal, flags);
451 } 454 }
452 455
453 return rc; 456 return rc;
454 } 457 }
455 458
456 /* 459 /*
457 ** Return the current file-size of an tvfs-file. 460 ** Return the current file-size of an tvfs-file.
458 */ 461 */
459 static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ 462 static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
460 TestvfsFd *p = tvfsGetFd(pFile); 463 TestvfsFd *p = tvfsGetFd(pFile);
461 return sqlite3OsFileSize(p->pReal, pSize); 464 return sqlite3OsFileSize(p->pReal, pSize);
462 } 465 }
463 466
464 /* 467 /*
465 ** Lock an tvfs-file. 468 ** Lock an tvfs-file.
466 */ 469 */
467 static int tvfsLock(sqlite3_file *pFile, int eLock){ 470 static int tvfsLock(sqlite3_file *pFile, int eLock){
468 TestvfsFd *p = tvfsGetFd(pFile); 471 TestvfsFd *pFd = tvfsGetFd(pFile);
469 return sqlite3OsLock(p->pReal, eLock); 472 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
473 if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
474 char zLock[30];
475 sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
476 tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
477 Tcl_NewStringObj(zLock, -1), 0, 0);
478 }
479 return sqlite3OsLock(pFd->pReal, eLock);
470 } 480 }
471 481
472 /* 482 /*
473 ** Unlock an tvfs-file. 483 ** Unlock an tvfs-file.
474 */ 484 */
475 static int tvfsUnlock(sqlite3_file *pFile, int eLock){ 485 static int tvfsUnlock(sqlite3_file *pFile, int eLock){
476 TestvfsFd *p = tvfsGetFd(pFile); 486 TestvfsFd *pFd = tvfsGetFd(pFile);
477 return sqlite3OsUnlock(p->pReal, eLock); 487 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
488 if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
489 char zLock[30];
490 sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
491 tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
492 Tcl_NewStringObj(zLock, -1), 0, 0);
493 }
494 if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
495 return SQLITE_IOERR_UNLOCK;
496 }
497 return sqlite3OsUnlock(pFd->pReal, eLock);
478 } 498 }
479 499
480 /* 500 /*
481 ** Check if another file-handle holds a RESERVED lock on an tvfs-file. 501 ** Check if another file-handle holds a RESERVED lock on an tvfs-file.
482 */ 502 */
483 static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ 503 static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
484 TestvfsFd *p = tvfsGetFd(pFile); 504 TestvfsFd *pFd = tvfsGetFd(pFile);
485 return sqlite3OsCheckReservedLock(p->pReal, pResOut); 505 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
506 if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
507 tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
508 0, 0, 0);
509 }
510 return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
486 } 511 }
487 512
488 /* 513 /*
489 ** File control method. For custom operations on an tvfs-file. 514 ** File control method. For custom operations on an tvfs-file.
490 */ 515 */
491 static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ 516 static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
492 TestvfsFd *p = tvfsGetFd(pFile); 517 TestvfsFd *p = tvfsGetFd(pFile);
518 if( op==SQLITE_FCNTL_PRAGMA ){
519 char **argv = (char**)pArg;
520 if( sqlite3_stricmp(argv[1],"error")==0 ){
521 int rc = SQLITE_ERROR;
522 if( argv[2] ){
523 const char *z = argv[2];
524 int x = atoi(z);
525 if( x ){
526 rc = x;
527 while( sqlite3Isdigit(z[0]) ){ z++; }
528 while( sqlite3Isspace(z[0]) ){ z++; }
529 }
530 if( z[0] ) argv[0] = sqlite3_mprintf("%s", z);
531 }
532 return rc;
533 }
534 if( sqlite3_stricmp(argv[1], "filename")==0 ){
535 argv[0] = sqlite3_mprintf("%s", p->zFilename);
536 return SQLITE_OK;
537 }
538 }
493 return sqlite3OsFileControl(p->pReal, op, pArg); 539 return sqlite3OsFileControl(p->pReal, op, pArg);
494 } 540 }
495 541
496 /* 542 /*
497 ** Return the sector-size in bytes for an tvfs-file. 543 ** Return the sector-size in bytes for an tvfs-file.
498 */ 544 */
499 static int tvfsSectorSize(sqlite3_file *pFile){ 545 static int tvfsSectorSize(sqlite3_file *pFile){
500 TestvfsFd *pFd = tvfsGetFd(pFile); 546 TestvfsFd *pFd = tvfsGetFd(pFile);
501 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 547 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
502 if( p->iSectorsize>=0 ){ 548 if( p->iSectorsize>=0 ){
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 pFd->pShm = 0; 584 pFd->pShm = 0;
539 pFd->pShmId = 0; 585 pFd->pShmId = 0;
540 pFd->zFilename = zName; 586 pFd->zFilename = zName;
541 pFd->pVfs = pVfs; 587 pFd->pVfs = pVfs;
542 pFd->pReal = (sqlite3_file *)&pFd[1]; 588 pFd->pReal = (sqlite3_file *)&pFd[1];
543 memset(pTestfile, 0, sizeof(TestvfsFile)); 589 memset(pTestfile, 0, sizeof(TestvfsFile));
544 pTestfile->pFd = pFd; 590 pTestfile->pFd = pFd;
545 591
546 /* Evaluate the Tcl script: 592 /* Evaluate the Tcl script:
547 ** 593 **
548 ** SCRIPT xOpen FILENAME 594 ** SCRIPT xOpen FILENAME KEY-VALUE-ARGS
549 ** 595 **
550 ** If the script returns an SQLite error code other than SQLITE_OK, an 596 ** If the script returns an SQLite error code other than SQLITE_OK, an
551 ** error is returned to the caller. If it returns SQLITE_OK, the new 597 ** error is returned to the caller. If it returns SQLITE_OK, the new
552 ** connection is named "anon". Otherwise, the value returned by the 598 ** connection is named "anon". Otherwise, the value returned by the
553 ** script is used as the connection name. 599 ** script is used as the connection name.
554 */ 600 */
555 Tcl_ResetResult(p->interp); 601 Tcl_ResetResult(p->interp);
556 if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){ 602 if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
557 tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); 603 Tcl_Obj *pArg = Tcl_NewObj();
604 Tcl_IncrRefCount(pArg);
605 if( flags&SQLITE_OPEN_MAIN_DB ){
606 const char *z = &zName[strlen(zName)+1];
607 while( *z ){
608 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
609 z += strlen(z) + 1;
610 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
611 z += strlen(z) + 1;
612 }
613 }
614 tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0);
615 Tcl_DecrRefCount(pArg);
558 if( tvfsResultCode(p, &rc) ){ 616 if( tvfsResultCode(p, &rc) ){
559 if( rc!=SQLITE_OK ) return rc; 617 if( rc!=SQLITE_OK ) return rc;
560 }else{ 618 }else{
561 pId = Tcl_GetObjResult(p->interp); 619 pId = Tcl_GetObjResult(p->interp);
562 } 620 }
563 } 621 }
564 622
565 if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR; 623 if( (p->mask&TESTVFS_OPEN_MASK) && tvfsInjectIoerr(p) ) return SQLITE_IOERR;
566 if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN; 624 if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN;
567 if( tvfsInjectFullerr(p) ) return SQLITE_FULL; 625 if( tvfsInjectFullerr(p) ) return SQLITE_FULL;
(...skipping 11 matching lines...) Expand all
579 int nByte; 637 int nByte;
580 638
581 if( pVfs->iVersion>1 ){ 639 if( pVfs->iVersion>1 ){
582 nByte = sizeof(sqlite3_io_methods); 640 nByte = sizeof(sqlite3_io_methods);
583 }else{ 641 }else{
584 nByte = offsetof(sqlite3_io_methods, xShmMap); 642 nByte = offsetof(sqlite3_io_methods, xShmMap);
585 } 643 }
586 644
587 pMethods = (sqlite3_io_methods *)ckalloc(nByte); 645 pMethods = (sqlite3_io_methods *)ckalloc(nByte);
588 memcpy(pMethods, &tvfs_io_methods, nByte); 646 memcpy(pMethods, &tvfs_io_methods, nByte);
589 pMethods->iVersion = pVfs->iVersion; 647 pMethods->iVersion = pFd->pReal->pMethods->iVersion;
648 if( pMethods->iVersion>pVfs->iVersion ){
649 pMethods->iVersion = pVfs->iVersion;
650 }
590 if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){ 651 if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){
591 pMethods->xShmUnmap = 0; 652 pMethods->xShmUnmap = 0;
592 pMethods->xShmLock = 0; 653 pMethods->xShmLock = 0;
593 pMethods->xShmBarrier = 0; 654 pMethods->xShmBarrier = 0;
594 pMethods->xShmMap = 0; 655 pMethods->xShmMap = 0;
595 } 656 }
596 pFile->pMethods = pMethods; 657 pFile->pMethods = pMethods;
597 } 658 }
598 659
599 return rc; 660 return rc;
600 } 661 }
601 662
602 /* 663 /*
603 ** Delete the file located at zPath. If the dirSync argument is true, 664 ** Delete the file located at zPath. If the dirSync argument is true,
604 ** ensure the file-system modifications are synced to disk before 665 ** ensure the file-system modifications are synced to disk before
605 ** returning. 666 ** returning.
606 */ 667 */
607 static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 668 static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
608 int rc = SQLITE_OK; 669 int rc = SQLITE_OK;
609 Testvfs *p = (Testvfs *)pVfs->pAppData; 670 Testvfs *p = (Testvfs *)pVfs->pAppData;
610 671
611 if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ 672 if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){
612 tvfsExecTcl(p, "xDelete", 673 tvfsExecTcl(p, "xDelete",
613 Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0 674 Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0
614 ); 675 );
615 tvfsResultCode(p, &rc); 676 tvfsResultCode(p, &rc);
616 } 677 }
617 if( rc==SQLITE_OK ){ 678 if( rc==SQLITE_OK ){
618 rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); 679 rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync);
619 } 680 }
620 return rc; 681 return rc;
621 } 682 }
622 683
623 /* 684 /*
624 ** Test for access permissions. Return true if the requested permission 685 ** Test for access permissions. Return true if the requested permission
625 ** is available, or false otherwise. 686 ** is available, or false otherwise.
626 */ 687 */
627 static int tvfsAccess( 688 static int tvfsAccess(
628 sqlite3_vfs *pVfs, 689 sqlite3_vfs *pVfs,
629 const char *zPath, 690 const char *zPath,
630 int flags, 691 int flags,
631 int *pResOut 692 int *pResOut
632 ){ 693 ){
633 Testvfs *p = (Testvfs *)pVfs->pAppData; 694 Testvfs *p = (Testvfs *)pVfs->pAppData;
634 if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){ 695 if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
635 int rc; 696 int rc;
636 char *zArg = 0; 697 char *zArg = 0;
637 if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; 698 if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
638 if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; 699 if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
639 if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; 700 if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
640 tvfsExecTcl(p, "xAccess", 701 tvfsExecTcl(p, "xAccess",
641 Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0 702 Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0
642 ); 703 );
643 if( tvfsResultCode(p, &rc) ){ 704 if( tvfsResultCode(p, &rc) ){
644 if( rc!=SQLITE_OK ) return rc; 705 if( rc!=SQLITE_OK ) return rc;
645 }else{ 706 }else{
646 Tcl_Interp *interp = p->interp; 707 Tcl_Interp *interp = p->interp;
647 if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){ 708 if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
648 return SQLITE_OK; 709 return SQLITE_OK;
649 } 710 }
650 } 711 }
651 } 712 }
652 return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut); 713 return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
653 } 714 }
654 715
655 /* 716 /*
656 ** Populate buffer zOut with the full canonical pathname corresponding 717 ** Populate buffer zOut with the full canonical pathname corresponding
657 ** to the pathname in zPath. zOut is guaranteed to point to a buffer 718 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
658 ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. 719 ** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
659 */ 720 */
660 static int tvfsFullPathname( 721 static int tvfsFullPathname(
661 sqlite3_vfs *pVfs, 722 sqlite3_vfs *pVfs,
662 const char *zPath, 723 const char *zPath,
663 int nOut, 724 int nOut,
664 char *zOut 725 char *zOut
665 ){ 726 ){
727 Testvfs *p = (Testvfs *)pVfs->pAppData;
728 if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
729 int rc;
730 tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0);
731 if( tvfsResultCode(p, &rc) ){
732 if( rc!=SQLITE_OK ) return rc;
733 }
734 }
666 return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); 735 return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
667 } 736 }
668 737
669 #ifndef SQLITE_OMIT_LOAD_EXTENSION 738 #ifndef SQLITE_OMIT_LOAD_EXTENSION
670 /* 739 /*
671 ** Open the dynamic library located at zPath and return a handle. 740 ** Open the dynamic library located at zPath and return a handle.
672 */ 741 */
673 static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ 742 static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
674 return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath); 743 return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath);
675 } 744 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 } 791 }
723 792
724 static int tvfsShmOpen(sqlite3_file *pFile){ 793 static int tvfsShmOpen(sqlite3_file *pFile){
725 Testvfs *p; 794 Testvfs *p;
726 int rc = SQLITE_OK; /* Return code */ 795 int rc = SQLITE_OK; /* Return code */
727 TestvfsBuffer *pBuffer; /* Buffer to open connection to */ 796 TestvfsBuffer *pBuffer; /* Buffer to open connection to */
728 TestvfsFd *pFd; /* The testvfs file structure */ 797 TestvfsFd *pFd; /* The testvfs file structure */
729 798
730 pFd = tvfsGetFd(pFile); 799 pFd = tvfsGetFd(pFile);
731 p = (Testvfs *)pFd->pVfs->pAppData; 800 p = (Testvfs *)pFd->pVfs->pAppData;
801 assert( 0==p->isFullshm );
732 assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 ); 802 assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 );
733 803
734 /* Evaluate the Tcl script: 804 /* Evaluate the Tcl script:
735 ** 805 **
736 ** SCRIPT xShmOpen FILENAME 806 ** SCRIPT xShmOpen FILENAME
737 */ 807 */
738 Tcl_ResetResult(p->interp); 808 Tcl_ResetResult(p->interp);
739 if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ 809 if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){
740 tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); 810 tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0);
741 if( tvfsResultCode(p, &rc) ){ 811 if( tvfsResultCode(p, &rc) ){
742 if( rc!=SQLITE_OK ) return rc; 812 if( rc!=SQLITE_OK ) return rc;
743 } 813 }
744 } 814 }
745 815
746 assert( rc==SQLITE_OK ); 816 assert( rc==SQLITE_OK );
747 if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){ 817 if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){
748 return SQLITE_IOERR; 818 return SQLITE_IOERR;
749 } 819 }
750 820
751 /* Search for a TestvfsBuffer. Create a new one if required. */ 821 /* Search for a TestvfsBuffer. Create a new one if required. */
752 for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ 822 for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
753 if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; 823 if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
754 } 824 }
755 if( !pBuffer ){ 825 if( !pBuffer ){
756 int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1; 826 int nByte = sizeof(TestvfsBuffer) + (int)strlen(pFd->zFilename) + 1;
757 pBuffer = (TestvfsBuffer *)ckalloc(nByte); 827 pBuffer = (TestvfsBuffer *)ckalloc(nByte);
758 memset(pBuffer, 0, nByte); 828 memset(pBuffer, 0, nByte);
759 pBuffer->zFile = (char *)&pBuffer[1]; 829 pBuffer->zFile = (char *)&pBuffer[1];
760 strcpy(pBuffer->zFile, pFd->zFilename); 830 strcpy(pBuffer->zFile, pFd->zFilename);
761 pBuffer->pNext = p->pBuffer; 831 pBuffer->pNext = p->pBuffer;
762 p->pBuffer = pBuffer; 832 p->pBuffer = pBuffer;
763 } 833 }
764 834
765 /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */ 835 /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
766 pFd->pNext = pBuffer->pFile; 836 pFd->pNext = pBuffer->pFile;
(...skipping 15 matching lines...) Expand all
782 sqlite3_file *pFile, /* Handle open on database file */ 852 sqlite3_file *pFile, /* Handle open on database file */
783 int iPage, /* Page to retrieve */ 853 int iPage, /* Page to retrieve */
784 int pgsz, /* Size of pages */ 854 int pgsz, /* Size of pages */
785 int isWrite, /* True to extend file if necessary */ 855 int isWrite, /* True to extend file if necessary */
786 void volatile **pp /* OUT: Mapped memory */ 856 void volatile **pp /* OUT: Mapped memory */
787 ){ 857 ){
788 int rc = SQLITE_OK; 858 int rc = SQLITE_OK;
789 TestvfsFd *pFd = tvfsGetFd(pFile); 859 TestvfsFd *pFd = tvfsGetFd(pFile);
790 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 860 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
791 861
862 if( p->isFullshm ){
863 return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp);
864 }
865
792 if( 0==pFd->pShm ){ 866 if( 0==pFd->pShm ){
793 rc = tvfsShmOpen(pFile); 867 rc = tvfsShmOpen(pFile);
794 if( rc!=SQLITE_OK ){ 868 if( rc!=SQLITE_OK ){
795 return rc; 869 return rc;
796 } 870 }
797 } 871 }
798 872
799 if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){ 873 if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
800 Tcl_Obj *pArg = Tcl_NewObj(); 874 Tcl_Obj *pArg = Tcl_NewObj();
801 Tcl_IncrRefCount(pArg); 875 Tcl_IncrRefCount(pArg);
802 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage)); 876 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
803 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); 877 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
804 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); 878 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
805 tvfsExecTcl(p, "xShmMap", 879 tvfsExecTcl(p, "xShmMap",
806 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg 880 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0
807 ); 881 );
808 tvfsResultCode(p, &rc); 882 tvfsResultCode(p, &rc);
809 Tcl_DecrRefCount(pArg); 883 Tcl_DecrRefCount(pArg);
810 } 884 }
811 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){ 885 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){
812 rc = SQLITE_IOERR; 886 rc = SQLITE_IOERR;
813 } 887 }
814 888
815 if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){ 889 if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
816 tvfsAllocPage(pFd->pShm, iPage, pgsz); 890 tvfsAllocPage(pFd->pShm, iPage, pgsz);
817 } 891 }
818 *pp = (void volatile *)pFd->pShm->aPage[iPage]; 892 *pp = (void volatile *)pFd->pShm->aPage[iPage];
819 893
820 return rc; 894 return rc;
821 } 895 }
822 896
823 897
824 static int tvfsShmLock( 898 static int tvfsShmLock(
825 sqlite3_file *pFile, 899 sqlite3_file *pFile,
826 int ofst, 900 int ofst,
827 int n, 901 int n,
828 int flags 902 int flags
829 ){ 903 ){
830 int rc = SQLITE_OK; 904 int rc = SQLITE_OK;
831 TestvfsFd *pFd = tvfsGetFd(pFile); 905 TestvfsFd *pFd = tvfsGetFd(pFile);
832 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 906 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
833 int nLock; 907 int nLock;
834 char zLock[80]; 908 char zLock[80];
835 909
910 if( p->isFullshm ){
911 return sqlite3OsShmLock(pFd->pReal, ofst, n, flags);
912 }
913
836 if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){ 914 if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
837 sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); 915 sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
838 nLock = strlen(zLock); 916 nLock = (int)strlen(zLock);
839 if( flags & SQLITE_SHM_LOCK ){ 917 if( flags & SQLITE_SHM_LOCK ){
840 strcpy(&zLock[nLock], " lock"); 918 strcpy(&zLock[nLock], " lock");
841 }else{ 919 }else{
842 strcpy(&zLock[nLock], " unlock"); 920 strcpy(&zLock[nLock], " unlock");
843 } 921 }
844 nLock += strlen(&zLock[nLock]); 922 nLock += (int)strlen(&zLock[nLock]);
845 if( flags & SQLITE_SHM_SHARED ){ 923 if( flags & SQLITE_SHM_SHARED ){
846 strcpy(&zLock[nLock], " shared"); 924 strcpy(&zLock[nLock], " shared");
847 }else{ 925 }else{
848 strcpy(&zLock[nLock], " exclusive"); 926 strcpy(&zLock[nLock], " exclusive");
849 } 927 }
850 tvfsExecTcl(p, "xShmLock", 928 tvfsExecTcl(p, "xShmLock",
851 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 929 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
852 Tcl_NewStringObj(zLock, -1) 930 Tcl_NewStringObj(zLock, -1), 0
853 ); 931 );
854 tvfsResultCode(p, &rc); 932 tvfsResultCode(p, &rc);
855 } 933 }
856 934
857 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){ 935 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){
858 rc = SQLITE_IOERR; 936 rc = SQLITE_IOERR;
859 } 937 }
860 938
861 if( rc==SQLITE_OK ){ 939 if( rc==SQLITE_OK ){
862 int isLock = (flags & SQLITE_SHM_LOCK); 940 int isLock = (flags & SQLITE_SHM_LOCK);
(...skipping 18 matching lines...) Expand all
881 } 959 }
882 } 960 }
883 961
884 return rc; 962 return rc;
885 } 963 }
886 964
887 static void tvfsShmBarrier(sqlite3_file *pFile){ 965 static void tvfsShmBarrier(sqlite3_file *pFile){
888 TestvfsFd *pFd = tvfsGetFd(pFile); 966 TestvfsFd *pFd = tvfsGetFd(pFile);
889 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 967 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
890 968
969 if( p->isFullshm ){
970 sqlite3OsShmBarrier(pFd->pReal);
971 return;
972 }
973
891 if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ 974 if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
892 tvfsExecTcl(p, "xShmBarrier", 975 tvfsExecTcl(p, "xShmBarrier",
893 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 976 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
894 ); 977 );
895 } 978 }
896 } 979 }
897 980
898 static int tvfsShmUnmap( 981 static int tvfsShmUnmap(
899 sqlite3_file *pFile, 982 sqlite3_file *pFile,
900 int deleteFlag 983 int deleteFlag
901 ){ 984 ){
902 int rc = SQLITE_OK; 985 int rc = SQLITE_OK;
903 TestvfsFd *pFd = tvfsGetFd(pFile); 986 TestvfsFd *pFd = tvfsGetFd(pFile);
904 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 987 Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
905 TestvfsBuffer *pBuffer = pFd->pShm; 988 TestvfsBuffer *pBuffer = pFd->pShm;
906 TestvfsFd **ppFd; 989 TestvfsFd **ppFd;
907 990
991 if( p->isFullshm ){
992 return sqlite3OsShmUnmap(pFd->pReal, deleteFlag);
993 }
994
908 if( !pBuffer ) return SQLITE_OK; 995 if( !pBuffer ) return SQLITE_OK;
909 assert( pFd->pShmId && pFd->pShm ); 996 assert( pFd->pShmId && pFd->pShm );
910 997
911 if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ 998 if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
912 tvfsExecTcl(p, "xShmUnmap", 999 tvfsExecTcl(p, "xShmUnmap",
913 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 1000 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0
914 ); 1001 );
915 tvfsResultCode(p, &rc); 1002 tvfsResultCode(p, &rc);
916 } 1003 }
917 1004
918 for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext)); 1005 for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext));
919 assert( (*ppFd)==pFd ); 1006 assert( (*ppFd)==pFd );
920 *ppFd = pFd->pNext; 1007 *ppFd = pFd->pNext;
921 pFd->pNext = 0; 1008 pFd->pNext = 0;
922 1009
923 if( pBuffer->pFile==0 ){ 1010 if( pBuffer->pFile==0 ){
924 int i; 1011 int i;
925 TestvfsBuffer **pp; 1012 TestvfsBuffer **pp;
926 for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext)); 1013 for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
927 *pp = (*pp)->pNext; 1014 *pp = (*pp)->pNext;
928 for(i=0; pBuffer->aPage[i]; i++){ 1015 for(i=0; pBuffer->aPage[i]; i++){
929 ckfree((char *)pBuffer->aPage[i]); 1016 ckfree((char *)pBuffer->aPage[i]);
930 } 1017 }
931 ckfree((char *)pBuffer); 1018 ckfree((char *)pBuffer);
932 } 1019 }
933 pFd->pShm = 0; 1020 pFd->pShm = 0;
934 1021
935 return rc; 1022 return rc;
936 } 1023 }
937 1024
1025 static int tvfsFetch(
1026 sqlite3_file *pFile,
1027 sqlite3_int64 iOfst,
1028 int iAmt,
1029 void **pp
1030 ){
1031 TestvfsFd *pFd = tvfsGetFd(pFile);
1032 return sqlite3OsFetch(pFd->pReal, iOfst, iAmt, pp);
1033 }
1034
1035 static int tvfsUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *p){
1036 TestvfsFd *pFd = tvfsGetFd(pFile);
1037 return sqlite3OsUnfetch(pFd->pReal, iOfst, p);
1038 }
1039
938 static int testvfs_obj_cmd( 1040 static int testvfs_obj_cmd(
939 ClientData cd, 1041 ClientData cd,
940 Tcl_Interp *interp, 1042 Tcl_Interp *interp,
941 int objc, 1043 int objc,
942 Tcl_Obj *CONST objv[] 1044 Tcl_Obj *CONST objv[]
943 ){ 1045 ){
944 Testvfs *p = (Testvfs *)cd; 1046 Testvfs *p = (Testvfs *)cd;
945 1047
946 enum DB_enum { 1048 enum DB_enum {
947 CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, 1049 CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT,
(...skipping 23 matching lines...) Expand all
971 if( Tcl_GetIndexFromObjStruct( 1073 if( Tcl_GetIndexFromObjStruct(
972 interp, objv[1], aSubcmd, sizeof(aSubcmd[0]), "subcommand", 0, &i) 1074 interp, objv[1], aSubcmd, sizeof(aSubcmd[0]), "subcommand", 0, &i)
973 ){ 1075 ){
974 return TCL_ERROR; 1076 return TCL_ERROR;
975 } 1077 }
976 Tcl_ResetResult(interp); 1078 Tcl_ResetResult(interp);
977 1079
978 switch( aSubcmd[i].eCmd ){ 1080 switch( aSubcmd[i].eCmd ){
979 case CMD_SHM: { 1081 case CMD_SHM: {
980 Tcl_Obj *pObj; 1082 Tcl_Obj *pObj;
981 int i; 1083 int i, rc;
982 TestvfsBuffer *pBuffer; 1084 TestvfsBuffer *pBuffer;
983 char *zName; 1085 char *zName;
984 if( objc!=3 && objc!=4 ){ 1086 if( objc!=3 && objc!=4 ){
985 Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?"); 1087 Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?");
986 return TCL_ERROR; 1088 return TCL_ERROR;
987 } 1089 }
988 zName = ckalloc(p->pParent->mxPathname); 1090 zName = ckalloc(p->pParent->mxPathname);
989 p->pParent->xFullPathname( 1091 rc = p->pParent->xFullPathname(
990 p->pParent, Tcl_GetString(objv[2]), 1092 p->pParent, Tcl_GetString(objv[2]),
991 p->pParent->mxPathname, zName 1093 p->pParent->mxPathname, zName
992 ); 1094 );
1095 if( rc!=SQLITE_OK ){
1096 Tcl_AppendResult(interp, "failed to get full path: ",
1097 Tcl_GetString(objv[2]), 0);
1098 ckfree(zName);
1099 return TCL_ERROR;
1100 }
993 for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ 1101 for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
994 if( 0==strcmp(pBuffer->zFile, zName) ) break; 1102 if( 0==strcmp(pBuffer->zFile, zName) ) break;
995 } 1103 }
996 ckfree(zName); 1104 ckfree(zName);
997 if( !pBuffer ){ 1105 if( !pBuffer ){
998 Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0); 1106 Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0);
999 return TCL_ERROR; 1107 return TCL_ERROR;
1000 } 1108 }
1001 if( objc==4 ){ 1109 if( objc==4 ){
1002 int n; 1110 int n;
(...skipping 13 matching lines...) Expand all
1016 pObj = Tcl_NewObj(); 1124 pObj = Tcl_NewObj();
1017 for(i=0; pBuffer->aPage[i]; i++){ 1125 for(i=0; pBuffer->aPage[i]; i++){
1018 int pgsz = pBuffer->pgsz; 1126 int pgsz = pBuffer->pgsz;
1019 if( pgsz==0 ) pgsz = 65536; 1127 if( pgsz==0 ) pgsz = 65536;
1020 Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz)); 1128 Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz));
1021 } 1129 }
1022 Tcl_SetObjResult(interp, pObj); 1130 Tcl_SetObjResult(interp, pObj);
1023 break; 1131 break;
1024 } 1132 }
1025 1133
1134 /* TESTVFS filter METHOD-LIST
1135 **
1136 ** Activate special processing for those methods contained in the list
1137 */
1026 case CMD_FILTER: { 1138 case CMD_FILTER: {
1027 static struct VfsMethod { 1139 static struct VfsMethod {
1028 char *zName; 1140 char *zName;
1029 int mask; 1141 int mask;
1030 } vfsmethod [] = { 1142 } vfsmethod [] = {
1031 { "xShmOpen", TESTVFS_SHMOPEN_MASK }, 1143 { "xShmOpen", TESTVFS_SHMOPEN_MASK },
1032 { "xShmLock", TESTVFS_SHMLOCK_MASK }, 1144 { "xShmLock", TESTVFS_SHMLOCK_MASK },
1033 { "xShmBarrier", TESTVFS_SHMBARRIER_MASK }, 1145 { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
1034 { "xShmUnmap", TESTVFS_SHMCLOSE_MASK }, 1146 { "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
1035 { "xShmMap", TESTVFS_SHMMAP_MASK }, 1147 { "xShmMap", TESTVFS_SHMMAP_MASK },
1036 { "xSync", TESTVFS_SYNC_MASK }, 1148 { "xSync", TESTVFS_SYNC_MASK },
1037 { "xDelete", TESTVFS_DELETE_MASK }, 1149 { "xDelete", TESTVFS_DELETE_MASK },
1038 { "xWrite", TESTVFS_WRITE_MASK }, 1150 { "xWrite", TESTVFS_WRITE_MASK },
1039 { "xTruncate", TESTVFS_TRUNCATE_MASK }, 1151 { "xRead", TESTVFS_READ_MASK },
1040 { "xOpen", TESTVFS_OPEN_MASK }, 1152 { "xTruncate", TESTVFS_TRUNCATE_MASK },
1041 { "xClose", TESTVFS_CLOSE_MASK }, 1153 { "xOpen", TESTVFS_OPEN_MASK },
1042 { "xAccess", TESTVFS_ACCESS_MASK }, 1154 { "xClose", TESTVFS_CLOSE_MASK },
1155 { "xAccess", TESTVFS_ACCESS_MASK },
1156 { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
1157 { "xUnlock", TESTVFS_UNLOCK_MASK },
1158 { "xLock", TESTVFS_LOCK_MASK },
1159 { "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
1043 }; 1160 };
1044 Tcl_Obj **apElem = 0; 1161 Tcl_Obj **apElem = 0;
1045 int nElem = 0; 1162 int nElem = 0;
1046 int i; 1163 int i;
1047 int mask = 0; 1164 int mask = 0;
1048 if( objc!=3 ){ 1165 if( objc!=3 ){
1049 Tcl_WrongNumArgs(interp, 2, objv, "LIST"); 1166 Tcl_WrongNumArgs(interp, 2, objv, "LIST");
1050 return TCL_ERROR; 1167 return TCL_ERROR;
1051 } 1168 }
1052 if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){ 1169 if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){
(...skipping 11 matching lines...) Expand all
1064 } 1181 }
1065 if( iMethod==ArraySize(vfsmethod) ){ 1182 if( iMethod==ArraySize(vfsmethod) ){
1066 Tcl_AppendResult(interp, "unknown method: ", zElem, 0); 1183 Tcl_AppendResult(interp, "unknown method: ", zElem, 0);
1067 return TCL_ERROR; 1184 return TCL_ERROR;
1068 } 1185 }
1069 } 1186 }
1070 p->mask = mask; 1187 p->mask = mask;
1071 break; 1188 break;
1072 } 1189 }
1073 1190
1191 /*
1192 ** TESTVFS script ?SCRIPT?
1193 **
1194 ** Query or set the script to be run when filtered VFS events
1195 ** occur.
1196 */
1074 case CMD_SCRIPT: { 1197 case CMD_SCRIPT: {
1075 if( objc==3 ){ 1198 if( objc==3 ){
1076 int nByte; 1199 int nByte;
1077 if( p->pScript ){ 1200 if( p->pScript ){
1078 Tcl_DecrRefCount(p->pScript); 1201 Tcl_DecrRefCount(p->pScript);
1079 ckfree((char *)p->apScript);
1080 p->apScript = 0;
1081 p->nScript = 0;
1082 p->pScript = 0; 1202 p->pScript = 0;
1083 } 1203 }
1084 Tcl_GetStringFromObj(objv[2], &nByte); 1204 Tcl_GetStringFromObj(objv[2], &nByte);
1085 if( nByte>0 ){ 1205 if( nByte>0 ){
1086 p->pScript = Tcl_DuplicateObj(objv[2]); 1206 p->pScript = Tcl_DuplicateObj(objv[2]);
1087 Tcl_IncrRefCount(p->pScript); 1207 Tcl_IncrRefCount(p->pScript);
1088 } 1208 }
1089 }else if( objc!=2 ){ 1209 }else if( objc!=2 ){
1090 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); 1210 Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
1091 return TCL_ERROR; 1211 return TCL_ERROR;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 Tcl_DeleteCommand(interp, Tcl_GetString(objv[0])); 1260 Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
1141 break; 1261 break;
1142 } 1262 }
1143 1263
1144 case CMD_DEVCHAR: { 1264 case CMD_DEVCHAR: {
1145 struct DeviceFlag { 1265 struct DeviceFlag {
1146 char *zName; 1266 char *zName;
1147 int iValue; 1267 int iValue;
1148 } aFlag[] = { 1268 } aFlag[] = {
1149 { "default", -1 }, 1269 { "default", -1 },
1150 { "atomic", SQLITE_IOCAP_ATOMIC }, 1270 { "atomic", SQLITE_IOCAP_ATOMIC },
1151 { "atomic512", SQLITE_IOCAP_ATOMIC512 }, 1271 { "atomic512", SQLITE_IOCAP_ATOMIC512 },
1152 { "atomic1k", SQLITE_IOCAP_ATOMIC1K }, 1272 { "atomic1k", SQLITE_IOCAP_ATOMIC1K },
1153 { "atomic2k", SQLITE_IOCAP_ATOMIC2K }, 1273 { "atomic2k", SQLITE_IOCAP_ATOMIC2K },
1154 { "atomic4k", SQLITE_IOCAP_ATOMIC4K }, 1274 { "atomic4k", SQLITE_IOCAP_ATOMIC4K },
1155 { "atomic8k", SQLITE_IOCAP_ATOMIC8K }, 1275 { "atomic8k", SQLITE_IOCAP_ATOMIC8K },
1156 { "atomic16k", SQLITE_IOCAP_ATOMIC16K }, 1276 { "atomic16k", SQLITE_IOCAP_ATOMIC16K },
1157 { "atomic32k", SQLITE_IOCAP_ATOMIC32K }, 1277 { "atomic32k", SQLITE_IOCAP_ATOMIC32K },
1158 { "atomic64k", SQLITE_IOCAP_ATOMIC64K }, 1278 { "atomic64k", SQLITE_IOCAP_ATOMIC64K },
1159 { "sequential", SQLITE_IOCAP_SEQUENTIAL }, 1279 { "sequential", SQLITE_IOCAP_SEQUENTIAL },
1160 { "safe_append", SQLITE_IOCAP_SAFE_APPEND }, 1280 { "safe_append", SQLITE_IOCAP_SAFE_APPEND },
1161 { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN }, 1281 { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
1282 { "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
1283 { "immutable", SQLITE_IOCAP_IMMUTABLE },
1162 { 0, 0 } 1284 { 0, 0 }
1163 }; 1285 };
1164 Tcl_Obj *pRet; 1286 Tcl_Obj *pRet;
1165 int iFlag; 1287 int iFlag;
1166 1288
1167 if( objc>3 ){ 1289 if( objc>3 ){
1168 Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?"); 1290 Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?");
1169 return TCL_ERROR; 1291 return TCL_ERROR;
1170 } 1292 }
1171 if( objc==3 ){ 1293 if( objc==3 ){
(...skipping 13 matching lines...) Expand all
1185 ){ 1307 ){
1186 return TCL_ERROR; 1308 return TCL_ERROR;
1187 } 1309 }
1188 if( aFlag[idx].iValue<0 && nFlags>1 ){ 1310 if( aFlag[idx].iValue<0 && nFlags>1 ){
1189 Tcl_AppendResult(interp, "bad flags: ", Tcl_GetString(objv[2]), 0); 1311 Tcl_AppendResult(interp, "bad flags: ", Tcl_GetString(objv[2]), 0);
1190 return TCL_ERROR; 1312 return TCL_ERROR;
1191 } 1313 }
1192 iNew |= aFlag[idx].iValue; 1314 iNew |= aFlag[idx].iValue;
1193 } 1315 }
1194 1316
1195 p->iDevchar = iNew; 1317 p->iDevchar = iNew| 0x10000000;
1196 } 1318 }
1197 1319
1198 pRet = Tcl_NewObj(); 1320 pRet = Tcl_NewObj();
1199 for(iFlag=0; iFlag<sizeof(aFlag)/sizeof(aFlag[0]); iFlag++){ 1321 for(iFlag=0; iFlag<sizeof(aFlag)/sizeof(aFlag[0]); iFlag++){
1200 if( p->iDevchar & aFlag[iFlag].iValue ){ 1322 if( p->iDevchar & aFlag[iFlag].iValue ){
1201 Tcl_ListObjAppendElement( 1323 Tcl_ListObjAppendElement(
1202 interp, pRet, Tcl_NewStringObj(aFlag[iFlag].zName, -1) 1324 interp, pRet, Tcl_NewStringObj(aFlag[iFlag].zName, -1)
1203 ); 1325 );
1204 } 1326 }
1205 } 1327 }
(...skipping 19 matching lines...) Expand all
1225 } 1347 }
1226 } 1348 }
1227 1349
1228 return TCL_OK; 1350 return TCL_OK;
1229 } 1351 }
1230 1352
1231 static void testvfs_obj_del(ClientData cd){ 1353 static void testvfs_obj_del(ClientData cd){
1232 Testvfs *p = (Testvfs *)cd; 1354 Testvfs *p = (Testvfs *)cd;
1233 if( p->pScript ) Tcl_DecrRefCount(p->pScript); 1355 if( p->pScript ) Tcl_DecrRefCount(p->pScript);
1234 sqlite3_vfs_unregister(p->pVfs); 1356 sqlite3_vfs_unregister(p->pVfs);
1235 ckfree((char *)p->apScript);
1236 ckfree((char *)p->pVfs); 1357 ckfree((char *)p->pVfs);
1237 ckfree((char *)p); 1358 ckfree((char *)p);
1238 } 1359 }
1239 1360
1240 /* 1361 /*
1241 ** Usage: testvfs VFSNAME ?SWITCHES? 1362 ** Usage: testvfs VFSNAME ?SWITCHES?
1242 ** 1363 **
1243 ** Switches are: 1364 ** Switches are:
1244 ** 1365 **
1245 ** -noshm BOOLEAN (True to omit shm methods. Default false) 1366 ** -noshm BOOLEAN (True to omit shm methods. Default false)
(...skipping 26 matching lines...) Expand all
1272 ** 1393 **
1273 ** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive" 1394 ** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive"
1274 */ 1395 */
1275 static int testvfs_cmd( 1396 static int testvfs_cmd(
1276 ClientData cd, 1397 ClientData cd,
1277 Tcl_Interp *interp, 1398 Tcl_Interp *interp,
1278 int objc, 1399 int objc,
1279 Tcl_Obj *CONST objv[] 1400 Tcl_Obj *CONST objv[]
1280 ){ 1401 ){
1281 static sqlite3_vfs tvfs_vfs = { 1402 static sqlite3_vfs tvfs_vfs = {
1282 2, /* iVersion */ 1403 3, /* iVersion */
1283 0, /* szOsFile */ 1404 0, /* szOsFile */
1284 0, /* mxPathname */ 1405 0, /* mxPathname */
1285 0, /* pNext */ 1406 0, /* pNext */
1286 0, /* zName */ 1407 0, /* zName */
1287 0, /* pAppData */ 1408 0, /* pAppData */
1288 tvfsOpen, /* xOpen */ 1409 tvfsOpen, /* xOpen */
1289 tvfsDelete, /* xDelete */ 1410 tvfsDelete, /* xDelete */
1290 tvfsAccess, /* xAccess */ 1411 tvfsAccess, /* xAccess */
1291 tvfsFullPathname, /* xFullPathname */ 1412 tvfsFullPathname, /* xFullPathname */
1292 #ifndef SQLITE_OMIT_LOAD_EXTENSION 1413 #ifndef SQLITE_OMIT_LOAD_EXTENSION
1293 tvfsDlOpen, /* xDlOpen */ 1414 tvfsDlOpen, /* xDlOpen */
1294 tvfsDlError, /* xDlError */ 1415 tvfsDlError, /* xDlError */
1295 tvfsDlSym, /* xDlSym */ 1416 tvfsDlSym, /* xDlSym */
1296 tvfsDlClose, /* xDlClose */ 1417 tvfsDlClose, /* xDlClose */
1297 #else 1418 #else
1298 0, /* xDlOpen */ 1419 0, /* xDlOpen */
1299 0, /* xDlError */ 1420 0, /* xDlError */
1300 0, /* xDlSym */ 1421 0, /* xDlSym */
1301 0, /* xDlClose */ 1422 0, /* xDlClose */
1302 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 1423 #endif /* SQLITE_OMIT_LOAD_EXTENSION */
1303 tvfsRandomness, /* xRandomness */ 1424 tvfsRandomness, /* xRandomness */
1304 tvfsSleep, /* xSleep */ 1425 tvfsSleep, /* xSleep */
1305 tvfsCurrentTime, /* xCurrentTime */ 1426 tvfsCurrentTime, /* xCurrentTime */
1306 0, /* xGetLastError */ 1427 0, /* xGetLastError */
1307 0, /* xCurrentTimeInt64 */ 1428 0, /* xCurrentTimeInt64 */
1429 0, /* xSetSystemCall */
1430 0, /* xGetSystemCall */
1431 0, /* xNextSystemCall */
1308 }; 1432 };
1309 1433
1310 Testvfs *p; /* New object */ 1434 Testvfs *p; /* New object */
1311 sqlite3_vfs *pVfs; /* New VFS */ 1435 sqlite3_vfs *pVfs; /* New VFS */
1312 char *zVfs; 1436 char *zVfs;
1313 int nByte; /* Bytes of space to allocate at p */ 1437 int nByte; /* Bytes of space to allocate at p */
1314 1438
1315 int i; 1439 int i;
1316 int isNoshm = 0; /* True if -noshm is passed */ 1440 int isNoshm = 0; /* True if -noshm is passed */
1441 int isFullshm = 0; /* True if -fullshm is passed */
1317 int isDefault = 0; /* True if -default is passed */ 1442 int isDefault = 0; /* True if -default is passed */
1318 int szOsFile = 0; /* Value passed to -szosfile */ 1443 int szOsFile = 0; /* Value passed to -szosfile */
1319 int mxPathname = -1; /* Value passed to -mxpathname */ 1444 int mxPathname = -1; /* Value passed to -mxpathname */
1320 int iVersion = 2; /* Value passed to -iversion */ 1445 int iVersion = 3; /* Value passed to -iversion */
1321 1446
1322 if( objc<2 || 0!=(objc%2) ) goto bad_args; 1447 if( objc<2 || 0!=(objc%2) ) goto bad_args;
1323 for(i=2; i<objc; i += 2){ 1448 for(i=2; i<objc; i += 2){
1324 int nSwitch; 1449 int nSwitch;
1325 char *zSwitch; 1450 char *zSwitch;
1326 zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch); 1451 zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch);
1327 1452
1328 if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ 1453 if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){
1329 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){ 1454 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){
1330 return TCL_ERROR; 1455 return TCL_ERROR;
1331 } 1456 }
1457 if( isNoshm ) isFullshm = 0;
1332 } 1458 }
1333 else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ 1459 else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){
1334 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){ 1460 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){
1335 return TCL_ERROR; 1461 return TCL_ERROR;
1336 } 1462 }
1337 } 1463 }
1338 else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ 1464 else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){
1339 if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){ 1465 if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){
1340 return TCL_ERROR; 1466 return TCL_ERROR;
1341 } 1467 }
1342 } 1468 }
1343 else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ 1469 else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){
1344 if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){ 1470 if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){
1345 return TCL_ERROR; 1471 return TCL_ERROR;
1346 } 1472 }
1347 } 1473 }
1348 else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){ 1474 else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){
1349 if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){ 1475 if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){
1350 return TCL_ERROR; 1476 return TCL_ERROR;
1351 } 1477 }
1352 } 1478 }
1479 else if( nSwitch>2 && 0==strncmp("-fullshm", zSwitch, nSwitch) ){
1480 if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isFullshm) ){
1481 return TCL_ERROR;
1482 }
1483 if( isFullshm ) isNoshm = 0;
1484 }
1353 else{ 1485 else{
1354 goto bad_args; 1486 goto bad_args;
1355 } 1487 }
1356 } 1488 }
1357 1489
1358 if( szOsFile<sizeof(TestvfsFile) ){ 1490 if( szOsFile<sizeof(TestvfsFile) ){
1359 szOsFile = sizeof(TestvfsFile); 1491 szOsFile = sizeof(TestvfsFile);
1360 } 1492 }
1361 1493
1362 zVfs = Tcl_GetString(objv[1]); 1494 zVfs = Tcl_GetString(objv[1]);
1363 nByte = sizeof(Testvfs) + strlen(zVfs)+1; 1495 nByte = sizeof(Testvfs) + (int)strlen(zVfs)+1;
1364 p = (Testvfs *)ckalloc(nByte); 1496 p = (Testvfs *)ckalloc(nByte);
1365 memset(p, 0, nByte); 1497 memset(p, 0, nByte);
1366 p->iDevchar = -1; 1498 p->iDevchar = -1;
1367 p->iSectorsize = -1; 1499 p->iSectorsize = -1;
1368 1500
1369 /* Create the new object command before querying SQLite for a default VFS 1501 /* Create the new object command before querying SQLite for a default VFS
1370 ** to use for 'real' IO operations. This is because creating the new VFS 1502 ** to use for 'real' IO operations. This is because creating the new VFS
1371 ** may delete an existing [testvfs] VFS of the same name. If such a VFS 1503 ** may delete an existing [testvfs] VFS of the same name. If such a VFS
1372 ** is currently the default, the new [testvfs] may end up calling the 1504 ** is currently the default, the new [testvfs] may end up calling the
1373 ** methods of a deleted object. 1505 ** methods of a deleted object.
(...skipping 10 matching lines...) Expand all
1384 pVfs->pAppData = (void *)p; 1516 pVfs->pAppData = (void *)p;
1385 pVfs->iVersion = iVersion; 1517 pVfs->iVersion = iVersion;
1386 pVfs->zName = p->zName; 1518 pVfs->zName = p->zName;
1387 pVfs->mxPathname = p->pParent->mxPathname; 1519 pVfs->mxPathname = p->pParent->mxPathname;
1388 if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){ 1520 if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){
1389 pVfs->mxPathname = mxPathname; 1521 pVfs->mxPathname = mxPathname;
1390 } 1522 }
1391 pVfs->szOsFile = szOsFile; 1523 pVfs->szOsFile = szOsFile;
1392 p->pVfs = pVfs; 1524 p->pVfs = pVfs;
1393 p->isNoshm = isNoshm; 1525 p->isNoshm = isNoshm;
1526 p->isFullshm = isFullshm;
1394 p->mask = TESTVFS_ALL_MASK; 1527 p->mask = TESTVFS_ALL_MASK;
1395 1528
1396 sqlite3_vfs_register(pVfs, isDefault); 1529 sqlite3_vfs_register(pVfs, isDefault);
1397 1530
1398 return TCL_OK; 1531 return TCL_OK;
1399 1532
1400 bad_args: 1533 bad_args:
1401 Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxp athname INT? ?-szosfile INT? ?-iversion INT?"); 1534 Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxp athname INT? ?-szosfile INT? ?-iversion INT?");
1402 return TCL_ERROR; 1535 return TCL_ERROR;
1403 } 1536 }
1404 1537
1405 int Sqlitetestvfs_Init(Tcl_Interp *interp){ 1538 int Sqlitetestvfs_Init(Tcl_Interp *interp){
1406 Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); 1539 Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
1407 return TCL_OK; 1540 return TCL_OK;
1408 } 1541 }
1409 1542
1410 #endif 1543 #endif
OLDNEW
« no previous file with comments | « third_party/sqlite/sqlite-src-3080704/src/test_thread.c ('k') | third_party/sqlite/sqlite-src-3080704/src/test_vfstrace.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698