4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
7 ** May you do good and not evil.
8 ** May you find forgiveness for yourself and forgive others.
9 ** May you share freely, never taking more than you give.
11 ******************************************************************************
13 ** This file contains code that is specific to Unix systems. It is used
14 ** for testing SQLite only.
16 #if OS_TEST /* This file is used for the test backend only */
17 #include "sqliteInt.h"
18 #include "os.h" /* Must be first to enable large file support */
20 #define sqlite3OsOpenReadWrite sqlite3RealOpenReadWrite
21 #define sqlite3OsOpenExclusive sqlite3RealOpenExclusive
22 #define sqlite3OsOpenReadOnly sqlite3RealOpenReadOnly
23 #define sqlite3OsOpenDirectory sqlite3RealOpenDirectory
24 #define sqlite3OsClose sqlite3RealClose
25 #define sqlite3OsRead sqlite3RealRead
26 #define sqlite3OsWrite sqlite3RealWrite
27 #define sqlite3OsSeek sqlite3RealSeek
28 #define sqlite3OsSync sqlite3RealSync
29 #define sqlite3OsTruncate sqlite3RealTruncate
30 #define sqlite3OsFileSize sqlite3RealFileSize
31 #define sqlite3OsLock sqlite3RealLock
32 #define sqlite3OsUnlock sqlite3RealUnlock
33 #define sqlite3OsCheckReservedLock sqlite3RealCheckReservedLock
35 #define OsFile OsRealFile
41 #undef sqlite3OsOpenReadWrite
42 #undef sqlite3OsOpenExclusive
43 #undef sqlite3OsOpenReadOnly
44 #undef sqlite3OsOpenDirectory
50 #undef sqlite3OsTruncate
51 #undef sqlite3OsFileSize
53 #undef sqlite3OsUnlock
54 #undef sqlite3OsCheckReservedLock
57 #define BLOCK_OFFSET(x) ((x) * BLOCKSIZE)
61 ** The following variables control when a simulated crash occurs.
63 ** If iCrashDelay is non-zero, then zCrashFile contains (full path) name of
64 ** a file that SQLite will call sqlite3OsSync() on. Each time this happens
65 ** iCrashDelay is decremented. If iCrashDelay is zero after being
66 ** decremented, a "crash" occurs during the sync() operation.
68 ** In other words, a crash occurs the iCrashDelay'th time zCrashFile is
71 static int iCrashDelay
= 0;
75 ** Set the value of the two crash parameters.
77 void sqlite3SetCrashParams(int iDelay
, char const *zFile
){
78 sqlite3OsEnterMutex();
79 assert( strlen(zFile
)<256 );
80 strcpy(zCrashFile
, zFile
);
82 sqlite3OsLeaveMutex();
86 ** File zPath is being sync()ed. Return non-zero if this should
89 static int crashRequired(char const *zPath
){
92 sqlite3OsEnterMutex();
93 n
= strlen(zCrashFile
);
94 if( zCrashFile
[n
-1]=='*' ){
96 }else if( strlen(zPath
)>n
){
100 if( iCrashDelay
>0 && strncmp(zPath
, zCrashFile
, n
)==0 ){
102 if( iCrashDelay
<=0 ){
106 sqlite3OsLeaveMutex();
111 static OsTestFile
*pAllFiles
= 0;
114 ** Initialise the os_test.c specific fields of pFile.
116 static void initFile(OsFile
*id
, char const *zName
){
117 OsTestFile
*pFile
= (OsTestFile
*)
118 sqliteMalloc(sizeof(OsTestFile
) + strlen(zName
)+1);
119 pFile
->nMaxWrite
= 0;
122 pFile
->zName
= (char *)(&pFile
[1]);
123 strcpy(pFile
->zName
, zName
);
125 pFile
->pNext
= pAllFiles
;
130 ** Undo the work done by initFile. Delete the OsTestFile structure
131 ** and unlink the structure from the pAllFiles list.
133 static void closeFile(OsFile
*id
){
134 OsTestFile
*pFile
= *id
;
135 if( pFile
==pAllFiles
){
136 pAllFiles
= pFile
->pNext
;
139 for(p
=pAllFiles
; p
->pNext
!=pFile
; p
=p
->pNext
){
142 p
->pNext
= pFile
->pNext
;
149 ** Return the current seek offset from the start of the file. This
150 ** is unix-only code.
152 static i64
osTell(OsTestFile
*pFile
){
153 return lseek(pFile
->fd
.h
, 0, SEEK_CUR
);
157 ** Load block 'blk' into the cache of pFile.
159 static int cacheBlock(OsTestFile
*pFile
, int blk
){
160 if( blk
>=pFile
->nBlk
){
161 int n
= ((pFile
->nBlk
* 2) + 100 + blk
);
162 /* if( pFile->nBlk==0 ){ printf("DIRTY %s\n", pFile->zName); } */
163 pFile
->apBlk
= (u8
**)sqliteRealloc(pFile
->apBlk
, n
* sizeof(u8
*));
164 if( !pFile
->apBlk
) return SQLITE_NOMEM
;
165 memset(&pFile
->apBlk
[pFile
->nBlk
], 0, (n
- pFile
->nBlk
)*sizeof(u8
*));
169 if( !pFile
->apBlk
[blk
] ){
173 u8
*p
= sqliteMalloc(BLOCKSIZE
);
174 if( !p
) return SQLITE_NOMEM
;
175 pFile
->apBlk
[blk
] = p
;
177 rc
= sqlite3RealFileSize(&pFile
->fd
, &filesize
);
178 if( rc
!=SQLITE_OK
) return rc
;
180 if( BLOCK_OFFSET(blk
)<filesize
){
182 rc
= sqlite3RealSeek(&pFile
->fd
, blk
*BLOCKSIZE
);
183 if( BLOCK_OFFSET(blk
+1)>filesize
){
184 len
= filesize
- BLOCK_OFFSET(blk
);
186 if( rc
!=SQLITE_OK
) return rc
;
187 rc
= sqlite3RealRead(&pFile
->fd
, p
, len
);
188 if( rc
!=SQLITE_OK
) return rc
;
195 /* #define TRACE_WRITECACHE */
198 ** Write the cache of pFile to disk. If crash is non-zero, randomly
199 ** skip blocks when writing. The cache is deleted before returning.
201 static int writeCache2(OsTestFile
*pFile
, int crash
){
203 int nMax
= pFile
->nMaxWrite
;
207 offset
= osTell(pFile
);
208 for(i
=0; i
<pFile
->nBlk
; i
++){
209 u8
*p
= pFile
->apBlk
[i
];
215 sqlite3Randomness(1, &random
);
219 #ifdef TRACE_WRITECACHE
220 printf("Trashing block %d of %s\n", i
, pFile
->zName
);
224 #ifdef TRACE_WRITECACHE
225 printf("Skiping block %d of %s\n", i
, pFile
->zName
);
229 #ifdef TRACE_WRITECACHE
230 printf("Writing block %d of %s\n", i
, pFile
->zName
);
235 rc
= sqlite3RealSeek(&pFile
->fd
, BLOCK_OFFSET(i
));
237 if( rc
==SQLITE_OK
&& !skip
){
239 if( BLOCK_OFFSET(i
+1)>nMax
){
240 len
= nMax
-BLOCK_OFFSET(i
);
244 sqlite3Randomness(len
, p
);
246 rc
= sqlite3RealWrite(&pFile
->fd
, p
, len
);
252 sqliteFree(pFile
->apBlk
);
255 pFile
->nMaxWrite
= 0;
258 rc
= sqlite3RealSeek(&pFile
->fd
, offset
);
264 ** Write the cache to disk.
266 static int writeCache(OsTestFile
*pFile
){
268 int c
= crashRequired(pFile
->zName
);
271 #ifdef TRACE_WRITECACHE
272 printf("\nCrash during sync of %s\n", pFile
->zName
);
274 for(p
=pAllFiles
; p
; p
=p
->pNext
){
279 return writeCache2(pFile
, 0);
288 int sqlite3OsClose(OsFile
*id
){
289 if( !(*id
) ) return SQLITE_OK
;
290 if( (*id
)->fd
.isOpen
){
291 /* printf("CLOSE %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */
293 sqlite3RealClose(&(*id
)->fd
);
299 int sqlite3OsRead(OsFile
*id
, void *pBuf
, int amt
){
300 i64 offset
; /* The current offset from the start of the file */
301 i64 end
; /* The byte just past the last byte read */
302 int blk
; /* Block number the read starts on */
306 OsTestFile
*pFile
= *id
;
308 offset
= osTell(pFile
);
310 blk
= (offset
/BLOCKSIZE
);
313 for(i
=blk
; i
*BLOCKSIZE
<end
; i
++){
318 if( BLOCK_OFFSET(i
) < offset
){
319 off
= offset
-BLOCK_OFFSET(i
);
321 len
= BLOCKSIZE
- off
;
322 if( BLOCK_OFFSET(i
+1) > end
){
323 len
= len
- (BLOCK_OFFSET(i
+1)-end
);
326 if( i
<pFile
->nBlk
&& pFile
->apBlk
[i
]){
327 u8
*pBlk
= pFile
->apBlk
[i
];
328 memcpy(zCsr
, &pBlk
[off
], len
);
330 rc
= sqlite3RealSeek(&pFile
->fd
, BLOCK_OFFSET(i
) + off
);
331 if( rc
!=SQLITE_OK
) return rc
;
332 rc
= sqlite3RealRead(&pFile
->fd
, zCsr
, len
);
333 if( rc
!=SQLITE_OK
) return rc
;
338 assert( zCsr
==&((u8
*)pBuf
)[amt
] );
340 rc
= sqlite3RealSeek(&pFile
->fd
, end
);
344 int sqlite3OsWrite(OsFile
*id
, const void *pBuf
, int amt
){
345 i64 offset
; /* The current offset from the start of the file */
346 i64 end
; /* The byte just past the last byte written */
347 int blk
; /* Block number the write starts on */
351 OsTestFile
*pFile
= *id
;
353 offset
= osTell(pFile
);
355 blk
= (offset
/BLOCKSIZE
);
358 for(i
=blk
; i
*BLOCKSIZE
<end
; i
++){
363 /* Make sure the block is in the cache */
364 rc
= cacheBlock(pFile
, i
);
365 if( rc
!=SQLITE_OK
) return rc
;
367 /* Write into the cache */
368 pBlk
= pFile
->apBlk
[i
];
371 if( BLOCK_OFFSET(i
) < offset
){
372 off
= offset
-BLOCK_OFFSET(i
);
374 len
= BLOCKSIZE
- off
;
375 if( BLOCK_OFFSET(i
+1) > end
){
376 len
= len
- (BLOCK_OFFSET(i
+1)-end
);
378 memcpy(&pBlk
[off
], zCsr
, len
);
381 if( pFile
->nMaxWrite
<end
){
382 pFile
->nMaxWrite
= end
;
384 assert( zCsr
==&((u8
*)pBuf
)[amt
] );
386 rc
= sqlite3RealSeek(&pFile
->fd
, end
);
391 ** Sync the file. First flush the write-cache to disk, then call the
392 ** real sync() function.
394 int sqlite3OsSync(OsFile
*id
){
396 /* printf("SYNC %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */
397 rc
= writeCache(*id
);
398 if( rc
!=SQLITE_OK
) return rc
;
399 rc
= sqlite3RealSync(&(*id
)->fd
);
404 ** Truncate the file. Set the internal OsFile.nMaxWrite variable to the new
405 ** file size to ensure that nothing in the write-cache past this point
406 ** is written to disk.
408 int sqlite3OsTruncate(OsFile
*id
, i64 nByte
){
409 (*id
)->nMaxWrite
= nByte
;
410 return sqlite3RealTruncate(&(*id
)->fd
, nByte
);
414 ** Return the size of the file. If the cache contains a write that extended
415 ** the file, then return this size instead of the on-disk size.
417 int sqlite3OsFileSize(OsFile
*id
, i64
*pSize
){
418 int rc
= sqlite3RealFileSize(&(*id
)->fd
, pSize
);
419 if( rc
==SQLITE_OK
&& pSize
&& *pSize
<(*id
)->nMaxWrite
){
420 *pSize
= (*id
)->nMaxWrite
;
426 ** The three functions used to open files. All that is required is to
427 ** initialise the os_test.c specific fields and then call the corresponding
428 ** os_unix.c function to really open the file.
430 int sqlite3OsOpenReadWrite(const char *zFilename
, OsFile
*id
, int *pReadonly
){
431 initFile(id
, zFilename
);
432 return sqlite3RealOpenReadWrite(zFilename
, &(*id
)->fd
, pReadonly
);
434 int sqlite3OsOpenExclusive(const char *zFilename
, OsFile
*id
, int delFlag
){
435 initFile(id
, zFilename
);
436 return sqlite3RealOpenExclusive(zFilename
, &(*id
)->fd
, delFlag
);
438 int sqlite3OsOpenReadOnly(const char *zFilename
, OsFile
*id
){
439 initFile(id
, zFilename
);
440 return sqlite3RealOpenReadOnly(zFilename
, &(*id
)->fd
);
444 ** These six function calls are passed straight through to the os_unix.c
447 int sqlite3OsSeek(OsFile
*id
, i64 offset
){
448 return sqlite3RealSeek(&(*id
)->fd
, offset
);
450 int sqlite3OsCheckReservedLock(OsFile
*id
){
451 return sqlite3RealCheckReservedLock(&(*id
)->fd
);
453 int sqlite3OsLock(OsFile
*id
, int locktype
){
454 return sqlite3RealLock(&(*id
)->fd
, locktype
);
456 int sqlite3OsUnlock(OsFile
*id
, int locktype
){
457 return sqlite3RealUnlock(&(*id
)->fd
, locktype
);
459 int sqlite3OsOpenDirectory(const char *zDirname
, OsFile
*id
){
460 return sqlite3RealOpenDirectory(zDirname
, &(*id
)->fd
);