xref: /sqlite-3.40.0/src/test_async.c (revision 74e4352a)
1 /*
2 ** 2005 December 14
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
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.
10 **
11 *************************************************************************
12 **
13 ** This file contains an example implementation of an asynchronous IO
14 ** backend for SQLite.
15 **
16 ** WHAT IS ASYNCHRONOUS I/O?
17 **
18 ** With asynchronous I/O, write requests are handled by a separate thread
19 ** running in the background.  This means that the thread that initiates
20 ** a database write does not have to wait for (sometimes slow) disk I/O
21 ** to occur.  The write seems to happen very quickly, though in reality
22 ** it is happening at its usual slow pace in the background.
23 **
24 ** Asynchronous I/O appears to give better responsiveness, but at a price.
25 ** You lose the Durable property.  With the default I/O backend of SQLite,
26 ** once a write completes, you know that the information you wrote is
27 ** safely on disk.  With the asynchronous I/O, this is no the case.  If
28 ** your program crashes or if you take a power lose after the database
29 ** write but before the asynchronous write thread has completed, then the
30 ** database change might never make it to disk and the next user of the
31 ** database might not see your change.
32 **
33 ** You lose Durability with asynchronous I/O, but you still retain the
34 ** other parts of ACID:  Atomic,  Consistent, and Isolated.  Many
35 ** appliations get along fine without the Durablity.
36 **
37 ** HOW IT WORKS
38 **
39 ** Asynchronous I/O works by overloading the OS-layer disk I/O routines
40 ** with modified versions that store the data to be written in queue of
41 ** pending write operations.  Look at the asyncEnable() subroutine to see
42 ** how overloading works.  Six os-layer routines are overloaded:
43 **
44 **     sqlite3OsOpenReadWrite;
45 **     sqlite3OsOpenReadOnly;
46 **     sqlite3OsOpenExclusive;
47 **     sqlite3OsDelete;
48 **     sqlite3OsFileExists;
49 **     sqlite3OsSyncDirectory;
50 **
51 ** The original implementations of these routines are saved and are
52 ** used by the writer thread to do the real I/O.  The substitute
53 ** implementations typically put the I/O operation on a queue
54 ** to be handled later by the writer thread, though read operations
55 ** must be handled right away, obviously.
56 **
57 ** Asynchronous I/O is disabled by setting the os-layer interface routines
58 ** back to their original values.
59 **
60 ** LIMITATIONS
61 **
62 ** This demonstration code is deliberately kept simple in order to keep
63 ** the main ideas clear and easy to understand.  Real applications that
64 ** want to do asynchronous I/O might want to add additional capabilities.
65 ** For example, in this demonstration if writes are happening at a steady
66 ** stream that exceeds the I/O capability of the background writer thread,
67 ** the queue of pending write operations will grow without bound until we
68 ** run out of memory.  Users of this technique may want to keep track of
69 ** the quantity of pending writes and stop accepting new write requests
70 ** when the buffer gets to be too big.
71 */
72 
73 #include "sqliteInt.h"
74 #include "os.h"
75 #include <tcl.h>
76 
77 /* If the THREADSAFE macro is not set, assume that it is turned off. */
78 #ifndef THREADSAFE
79 # define THREADSAFE 0
80 #endif
81 
82 /*
83 ** This test uses pthreads and hence only works on unix and with
84 ** a threadsafe build of SQLite.  It also requires that the redefinable
85 ** I/O feature of SQLite be turned on.  This feature is turned off by
86 ** default.  If a required element is missing, almost all of the code
87 ** in this file is commented out.
88 */
89 #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO)
90 
91 /*
92 ** This demo uses pthreads.  If you do not have a pthreads implementation
93 ** for your operating system, you will need to recode the threading
94 ** logic.
95 */
96 #include <pthread.h>
97 #include <sched.h>
98 
99 /* Useful macros used in several places */
100 #define MIN(x,y) ((x)<(y)?(x):(y))
101 #define MAX(x,y) ((x)>(y)?(x):(y))
102 
103 /* Forward references */
104 typedef struct AsyncWrite AsyncWrite;
105 typedef struct AsyncFile AsyncFile;
106 
107 /* Enable for debugging */
108 static int sqlite3async_trace = 0;
109 # define TRACE(X) if( sqlite3async_trace ) asyncTrace X
110 static void asyncTrace(const char *zFormat, ...){
111   char *z;
112   va_list ap;
113   va_start(ap, zFormat);
114   z = sqlite3_vmprintf(zFormat, ap);
115   va_end(ap);
116   fprintf(stderr, "[%d] %s", (int)pthread_self(), z);
117   free(z);
118 }
119 
120 /*
121 ** THREAD SAFETY NOTES
122 **
123 ** Basic rules:
124 **
125 **     * Both read and write access to the global write-op queue must be
126 **       protected by the async.queueMutex.
127 **
128 **     * The file handles from the underlying system are assumed not to
129 **       be thread safe.
130 **
131 **     * See the last two paragraphs under "The Writer Thread" for
132 **       an assumption to do with file-handle synchronization by the Os.
133 **
134 ** File system operations (invoked by SQLite thread):
135 **
136 **     xOpenXXX (three versions)
137 **     xDelete
138 **     xFileExists
139 **     xSyncDirectory
140 **
141 ** File handle operations (invoked by SQLite thread):
142 **
143 **         asyncWrite, asyncClose, asyncTruncate, asyncSync,
144 **         asyncSetFullSync, asyncOpenDirectory.
145 **
146 **     The operations above add an entry to the global write-op list. They
147 **     prepare the entry, acquire the async.queueMutex momentarily while
148 **     list pointers are  manipulated to insert the new entry, then release
149 **     the mutex and signal the writer thread to wake up in case it happens
150 **     to be asleep.
151 **
152 **
153 **         asyncRead, asyncFileSize.
154 **
155 **     Read operations. Both of these read from both the underlying file
156 **     first then adjust their result based on pending writes in the
157 **     write-op queue.   So async.queueMutex is held for the duration
158 **     of these operations to prevent other threads from changing the
159 **     queue in mid operation.
160 **
161 **
162 **         asyncLock, asyncUnlock, asyncLockState, asyncCheckReservedLock
163 **
164 **     These primitives implement in-process locking using a hash table
165 **     on the file name.  Files are locked correctly for connections coming
166 **     from the same process.  But other processes cannot see these locks
167 **     and will therefore not honor them.
168 **
169 **
170 **         asyncFileHandle.
171 **
172 **     The sqlite3OsFileHandle() function is currently only used when
173 **     debugging the pager module. Unless sqlite3OsClose() is called on the
174 **     file (shouldn't be possible for other reasons), the underlying
175 **     implementations are safe to call without grabbing any mutex. So we just
176 **     go ahead and call it no matter what any other threads are doing.
177 **
178 **
179 **         asyncSeek.
180 **
181 **     Calling this method just manipulates the AsyncFile.iOffset variable.
182 **     Since this variable is never accessed by writer thread, this
183 **     function does not require the mutex.  Actual calls to OsSeek() take
184 **     place just before OsWrite() or OsRead(), which are always protected by
185 **     the mutex.
186 **
187 ** The writer thread:
188 **
189 **     The async.writerMutex is used to make sure only there is only
190 **     a single writer thread running at a time.
191 **
192 **     Inside the writer thread is a loop that works like this:
193 **
194 **         WHILE (write-op list is not empty)
195 **             Do IO operation at head of write-op list
196 **             Remove entry from head of write-op list
197 **         END WHILE
198 **
199 **     The async.queueMutex is always held during the <write-op list is
200 **     not empty> test, and when the entry is removed from the head
201 **     of the write-op list. Sometimes it is held for the interim
202 **     period (while the IO is performed), and sometimes it is
203 **     relinquished. It is relinquished if (a) the IO op is an
204 **     ASYNC_CLOSE or (b) when the file handle was opened, two of
205 **     the underlying systems handles were opened on the same
206 **     file-system entry.
207 **
208 **     If condition (b) above is true, then one file-handle
209 **     (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the
210 **     file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush()
211 **     threads to perform write() operations. This means that read
212 **     operations are not blocked by asynchronous writes (although
213 **     asynchronous writes may still be blocked by reads).
214 **
215 **     This assumes that the OS keeps two handles open on the same file
216 **     properly in sync. That is, any read operation that starts after a
217 **     write operation on the same file system entry has completed returns
218 **     data consistent with the write. We also assume that if one thread
219 **     reads a file while another is writing it all bytes other than the
220 **     ones actually being written contain valid data.
221 **
222 **     If the above assumptions are not true, set the preprocessor symbol
223 **     SQLITE_ASYNC_TWO_FILEHANDLES to 0.
224 */
225 
226 #ifndef SQLITE_ASYNC_TWO_FILEHANDLES
227 /* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */
228 #define SQLITE_ASYNC_TWO_FILEHANDLES 1
229 #endif
230 
231 /*
232 ** State information is held in the static variable "async" defined
233 ** as follows:
234 */
235 static struct TestAsyncStaticData {
236   pthread_mutex_t queueMutex;  /* Mutex for access to write operation queue */
237   pthread_mutex_t writerMutex; /* Prevents multiple writer threads */
238   pthread_mutex_t lockMutex;   /* For access to aLock hash table */
239   pthread_cond_t queueSignal;  /* For waking up sleeping writer thread */
240   pthread_cond_t emptySignal;  /* Notify when the write queue is empty */
241   AsyncWrite *pQueueFirst;     /* Next write operation to be processed */
242   AsyncWrite *pQueueLast;      /* Last write operation on the list */
243   Hash aLock;                  /* Files locked */
244   volatile int ioDelay;             /* Extra delay between write operations */
245   volatile int writerHaltWhenIdle;  /* Writer thread halts when queue empty */
246   volatile int writerHaltNow;       /* Writer thread halts after next op */
247   int ioError;                 /* True if an IO error has occured */
248   int nFile;                   /* Number of open files (from sqlite pov) */
249 } async = {
250   PTHREAD_MUTEX_INITIALIZER,
251   PTHREAD_MUTEX_INITIALIZER,
252   PTHREAD_MUTEX_INITIALIZER,
253   PTHREAD_COND_INITIALIZER,
254   PTHREAD_COND_INITIALIZER,
255 };
256 
257 /* Possible values of AsyncWrite.op */
258 #define ASYNC_NOOP          0
259 #define ASYNC_WRITE         1
260 #define ASYNC_SYNC          2
261 #define ASYNC_TRUNCATE      3
262 #define ASYNC_CLOSE         4
263 #define ASYNC_OPENDIRECTORY 5
264 #define ASYNC_SETFULLSYNC   6
265 #define ASYNC_DELETE        7
266 #define ASYNC_OPENEXCLUSIVE 8
267 #define ASYNC_SYNCDIRECTORY 9
268 
269 /* Names of opcodes.  Used for debugging only.
270 ** Make sure these stay in sync with the macros above!
271 */
272 static const char *azOpcodeName[] = {
273   "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE",
274   "OPENDIR", "SETFULLSYNC", "DELETE", "OPENEX", "SYNCDIR",
275 };
276 
277 /*
278 ** Entries on the write-op queue are instances of the AsyncWrite
279 ** structure, defined here.
280 **
281 ** The interpretation of the iOffset and nByte variables varies depending
282 ** on the value of AsyncWrite.op:
283 **
284 ** ASYNC_WRITE:
285 **     iOffset -> Offset in file to write to.
286 **     nByte   -> Number of bytes of data to write (pointed to by zBuf).
287 **
288 ** ASYNC_SYNC:
289 **     iOffset -> Unused.
290 **     nByte   -> Value of "fullsync" flag to pass to sqlite3OsSync().
291 **
292 ** ASYNC_TRUNCATE:
293 **     iOffset -> Size to truncate file to.
294 **     nByte   -> Unused.
295 **
296 ** ASYNC_CLOSE:
297 **     iOffset -> Unused.
298 **     nByte   -> Unused.
299 **
300 ** ASYNC_OPENDIRECTORY:
301 **     iOffset -> Unused.
302 **     nByte   -> Number of bytes of zBuf points to (directory name).
303 **
304 ** ASYNC_SETFULLSYNC:
305 **     iOffset -> Unused.
306 **     nByte   -> New value for the full-sync flag.
307 **
308 **
309 ** ASYNC_DELETE:
310 **     iOffset -> Unused.
311 **     nByte   -> Number of bytes of zBuf points to (file name).
312 **
313 ** ASYNC_OPENEXCLUSIVE:
314 **     iOffset -> Value of "delflag".
315 **     nByte   -> Number of bytes of zBuf points to (file name).
316 **
317 **
318 ** For an ASYNC_WRITE operation, zBuf points to the data to write to the file.
319 ** This space is sqliteMalloc()d along with the AsyncWrite structure in a
320 ** single blob, so is deleted when sqliteFree() is called on the parent
321 ** structure.
322 */
323 struct AsyncWrite {
324   AsyncFile *pFile;   /* File to write data to or sync */
325   int op;             /* One of ASYNC_xxx etc. */
326   i64 iOffset;        /* See above */
327   int nByte;          /* See above */
328   char *zBuf;         /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
329   AsyncWrite *pNext;  /* Next write operation (to any file) */
330 };
331 
332 /*
333 ** The AsyncFile structure is a subclass of OsFile used for asynchronous IO.
334 */
335 struct AsyncFile {
336   IoMethod *pMethod;   /* Must be first */
337   i64 iOffset;         /* Current seek() offset in file */
338   char *zName;         /* Underlying OS filename - used for debugging */
339   int nName;           /* Number of characters in zName */
340   OsFile *pBaseRead;   /* Read handle to the underlying Os file */
341   OsFile *pBaseWrite;  /* Write handle to the underlying Os file */
342 };
343 
344 /*
345 ** Add an entry to the end of the global write-op list. pWrite should point
346 ** to an AsyncWrite structure allocated using sqlite3OsMalloc().  The writer
347 ** thread will call sqlite3OsFree() to free the structure after the specified
348 ** operation has been completed.
349 **
350 ** Once an AsyncWrite structure has been added to the list, it becomes the
351 ** property of the writer thread and must not be read or modified by the
352 ** caller.
353 */
354 static void addAsyncWrite(AsyncWrite *pWrite){
355   /* We must hold the queue mutex in order to modify the queue pointers */
356   pthread_mutex_lock(&async.queueMutex);
357 
358   /* Add the record to the end of the write-op queue */
359   assert( !pWrite->pNext );
360   if( async.pQueueLast ){
361     assert( async.pQueueFirst );
362     async.pQueueLast->pNext = pWrite;
363   }else{
364     async.pQueueFirst = pWrite;
365   }
366   async.pQueueLast = pWrite;
367   TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op],
368          pWrite->pFile ? pWrite->pFile->zName : "-", pWrite->iOffset));
369 
370   if( pWrite->op==ASYNC_CLOSE ){
371     async.nFile--;
372     if( async.nFile==0 ){
373       async.ioError = SQLITE_OK;
374     }
375   }
376 
377   /* Drop the queue mutex */
378   pthread_mutex_unlock(&async.queueMutex);
379 
380   /* The writer thread might have been idle because there was nothing
381   ** on the write-op queue for it to do.  So wake it up. */
382   pthread_cond_signal(&async.queueSignal);
383 }
384 
385 /*
386 ** Increment async.nFile in a thread-safe manner.
387 */
388 static void incrOpenFileCount(){
389   /* We must hold the queue mutex in order to modify async.nFile */
390   pthread_mutex_lock(&async.queueMutex);
391   if( async.nFile==0 ){
392     async.ioError = SQLITE_OK;
393   }
394   async.nFile++;
395   pthread_mutex_unlock(&async.queueMutex);
396 }
397 
398 /*
399 ** This is a utility function to allocate and populate a new AsyncWrite
400 ** structure and insert it (via addAsyncWrite() ) into the global list.
401 */
402 static int addNewAsyncWrite(
403   AsyncFile *pFile,
404   int op,
405   i64 iOffset,
406   int nByte,
407   const char *zByte
408 ){
409   AsyncWrite *p;
410   if( op!=ASYNC_CLOSE && async.ioError ){
411     return async.ioError;
412   }
413   p = sqlite3OsMalloc(sizeof(AsyncWrite) + (zByte?nByte:0));
414   if( !p ){
415     return SQLITE_NOMEM;
416   }
417   p->op = op;
418   p->iOffset = iOffset;
419   p->nByte = nByte;
420   p->pFile = pFile;
421   p->pNext = 0;
422   if( zByte ){
423     p->zBuf = (char *)&p[1];
424     memcpy(p->zBuf, zByte, nByte);
425   }else{
426     p->zBuf = 0;
427   }
428   addAsyncWrite(p);
429   return SQLITE_OK;
430 }
431 
432 /*
433 ** Close the file. This just adds an entry to the write-op list, the file is
434 ** not actually closed.
435 */
436 static int asyncClose(OsFile **pId){
437   return addNewAsyncWrite((AsyncFile *)*pId, ASYNC_CLOSE, 0, 0, 0);
438 }
439 
440 /*
441 ** Implementation of sqlite3OsWrite() for asynchronous files. Instead of
442 ** writing to the underlying file, this function adds an entry to the end of
443 ** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
444 ** returned.
445 */
446 static int asyncWrite(OsFile *id, const void *pBuf, int amt){
447   AsyncFile *pFile = (AsyncFile *)id;
448   int rc = addNewAsyncWrite(pFile, ASYNC_WRITE, pFile->iOffset, amt, pBuf);
449   pFile->iOffset += (i64)amt;
450   return rc;
451 }
452 
453 /*
454 ** Truncate the file to nByte bytes in length. This just adds an entry to
455 ** the write-op list, no IO actually takes place.
456 */
457 static int asyncTruncate(OsFile *id, i64 nByte){
458   return addNewAsyncWrite((AsyncFile *)id, ASYNC_TRUNCATE, nByte, 0, 0);
459 }
460 
461 /*
462 ** Open the directory identified by zName and associate it with the
463 ** specified file. This just adds an entry to the write-op list, the
464 ** directory is opened later by sqlite3_async_flush().
465 */
466 static int asyncOpenDirectory(OsFile *id, const char *zName){
467   AsyncFile *pFile = (AsyncFile *)id;
468   return addNewAsyncWrite(pFile, ASYNC_OPENDIRECTORY, 0, strlen(zName)+1,zName);
469 }
470 
471 /*
472 ** Sync the file. This just adds an entry to the write-op list, the
473 ** sync() is done later by sqlite3_async_flush().
474 */
475 static int asyncSync(OsFile *id, int fullsync){
476   return addNewAsyncWrite((AsyncFile *)id, ASYNC_SYNC, 0, fullsync, 0);
477 }
478 
479 /*
480 ** Set (or clear) the full-sync flag on the underlying file. This operation
481 ** is queued and performed later by sqlite3_async_flush().
482 */
483 static void asyncSetFullSync(OsFile *id, int value){
484   addNewAsyncWrite((AsyncFile *)id, ASYNC_SETFULLSYNC, 0, value, 0);
485 }
486 
487 /*
488 ** Read data from the file. First we read from the filesystem, then adjust
489 ** the contents of the buffer based on ASYNC_WRITE operations in the
490 ** write-op queue.
491 **
492 ** This method holds the mutex from start to finish.
493 */
494 static int asyncRead(OsFile *id, void *obuf, int amt){
495   int rc = SQLITE_OK;
496   i64 filesize;
497   int nRead;
498   AsyncFile *pFile = (AsyncFile *)id;
499   OsFile *pBase = pFile->pBaseRead;
500 
501   /* If an I/O error has previously occurred on this file, then all
502   ** subsequent operations fail.
503   */
504   if( async.ioError!=SQLITE_OK ){
505     return async.ioError;
506   }
507 
508   /* Grab the write queue mutex for the duration of the call */
509   pthread_mutex_lock(&async.queueMutex);
510 
511   if( pBase ){
512     rc = sqlite3OsFileSize(pBase, &filesize);
513     if( rc!=SQLITE_OK ){
514       goto asyncread_out;
515     }
516     rc = sqlite3OsSeek(pBase, pFile->iOffset);
517     if( rc!=SQLITE_OK ){
518       goto asyncread_out;
519     }
520     nRead = MIN(filesize - pFile->iOffset, amt);
521     if( nRead>0 ){
522       rc = sqlite3OsRead(pBase, obuf, nRead);
523       TRACE(("READ %s %d bytes at %d\n", pFile->zName, nRead, pFile->iOffset));
524     }
525   }
526 
527   if( rc==SQLITE_OK ){
528     AsyncWrite *p;
529     i64 iOffset = pFile->iOffset;           /* Current seek offset */
530 
531     for(p=async.pQueueFirst; p; p = p->pNext){
532       if( p->pFile==pFile && p->op==ASYNC_WRITE ){
533         int iBeginOut = (p->iOffset - iOffset);
534         int iBeginIn = -iBeginOut;
535         int nCopy;
536 
537         if( iBeginIn<0 ) iBeginIn = 0;
538         if( iBeginOut<0 ) iBeginOut = 0;
539         nCopy = MIN(p->nByte-iBeginIn, amt-iBeginOut);
540 
541         if( nCopy>0 ){
542           memcpy(&((char *)obuf)[iBeginOut], &p->zBuf[iBeginIn], nCopy);
543           TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset));
544         }
545       }
546     }
547 
548     pFile->iOffset += (i64)amt;
549   }
550 
551 asyncread_out:
552   pthread_mutex_unlock(&async.queueMutex);
553   return rc;
554 }
555 
556 /*
557 ** Seek to the specified offset. This just adjusts the AsyncFile.iOffset
558 ** variable - calling seek() on the underlying file is defered until the
559 ** next read() or write() operation.
560 */
561 static int asyncSeek(OsFile *id, i64 offset){
562   AsyncFile *pFile = (AsyncFile *)id;
563   pFile->iOffset = offset;
564   return SQLITE_OK;
565 }
566 
567 /*
568 ** Read the size of the file. First we read the size of the file system
569 ** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations
570 ** currently in the write-op list.
571 **
572 ** This method holds the mutex from start to finish.
573 */
574 int asyncFileSize(OsFile *id, i64 *pSize){
575   int rc = SQLITE_OK;
576   i64 s = 0;
577   OsFile *pBase;
578 
579   pthread_mutex_lock(&async.queueMutex);
580 
581   /* Read the filesystem size from the base file. If pBaseRead is NULL, this
582   ** means the file hasn't been opened yet. In this case all relevant data
583   ** must be in the write-op queue anyway, so we can omit reading from the
584   ** file-system.
585   */
586   pBase = ((AsyncFile *)id)->pBaseRead;
587   if( pBase ){
588     rc = sqlite3OsFileSize(pBase, &s);
589   }
590 
591   if( rc==SQLITE_OK ){
592     AsyncWrite *p;
593     for(p=async.pQueueFirst; p; p = p->pNext){
594       if( p->pFile==(AsyncFile *)id ){
595         switch( p->op ){
596           case ASYNC_WRITE:
597             s = MAX(p->iOffset + (i64)(p->nByte), s);
598             break;
599           case ASYNC_TRUNCATE:
600             s = MIN(s, p->iOffset);
601             break;
602         }
603       }
604     }
605     *pSize = s;
606   }
607   pthread_mutex_unlock(&async.queueMutex);
608   return rc;
609 }
610 
611 /*
612 ** Return the operating system file handle. This is only used for debugging
613 ** at the moment anyway.
614 */
615 static int asyncFileHandle(OsFile *id){
616   return sqlite3OsFileHandle(((AsyncFile *)id)->pBaseRead);
617 }
618 
619 /*
620 ** No disk locking is performed.  We keep track of locks locally in
621 ** the async.aLock hash table.  Locking should appear to work the same
622 ** as with standard (unmodified) SQLite as long as all connections
623 ** come from this one process.  Connections from external processes
624 ** cannot see our internal hash table (obviously) and will thus not
625 ** honor our locks.
626 */
627 static int asyncLock(OsFile *id, int lockType){
628   AsyncFile *pFile = (AsyncFile*)id;
629   TRACE(("LOCK %d (%s)\n", lockType, pFile->zName));
630   pthread_mutex_lock(&async.lockMutex);
631   sqlite3HashInsert(&async.aLock, pFile->zName, pFile->nName, (void*)lockType);
632   pthread_mutex_unlock(&async.lockMutex);
633   return SQLITE_OK;
634 }
635 static int asyncUnlock(OsFile *id, int lockType){
636   return asyncLock(id, lockType);
637 }
638 
639 /*
640 ** This function is called when the pager layer first opens a database file
641 ** and is checking for a hot-journal.
642 */
643 static int asyncCheckReservedLock(OsFile *id){
644   AsyncFile *pFile = (AsyncFile*)id;
645   int rc;
646   pthread_mutex_lock(&async.lockMutex);
647   rc = (int)sqlite3HashFind(&async.aLock, pFile->zName, pFile->nName);
648   pthread_mutex_unlock(&async.lockMutex);
649   TRACE(("CHECK-LOCK %d (%s)\n", rc, pFile->zName));
650   return rc>SHARED_LOCK;
651 }
652 
653 /*
654 ** This is broken. But sqlite3OsLockState() is only used for testing anyway.
655 */
656 static int asyncLockState(OsFile *id){
657   return SQLITE_OK;
658 }
659 
660 /*
661 ** The following variables hold pointers to the original versions of
662 ** OS-layer interface routines that are overloaded in order to create
663 ** the asynchronous I/O backend.
664 */
665 static int (*xOrigOpenReadWrite)(const char*, OsFile**, int*) = 0;
666 static int (*xOrigOpenExclusive)(const char*, OsFile**, int) = 0;
667 static int (*xOrigOpenReadOnly)(const char*, OsFile**) = 0;
668 static int (*xOrigDelete)(const char*) = 0;
669 static int (*xOrigFileExists)(const char*) = 0;
670 static int (*xOrigSyncDirectory)(const char*) = 0;
671 
672 /*
673 ** This routine does most of the work of opening a file and building
674 ** the OsFile structure.
675 */
676 static int asyncOpenFile(
677   const char *zName,     /* The name of the file to be opened */
678   OsFile **pFile,        /* Put the OsFile structure here */
679   OsFile *pBaseRead,     /* The real OsFile from the real I/O routine */
680   int openForWriting     /* Open a second file handle for writing if true */
681 ){
682   int rc, i, n;
683   AsyncFile *p;
684   OsFile *pBaseWrite = 0;
685 
686   static IoMethod iomethod = {
687     asyncClose,
688     asyncOpenDirectory,
689     asyncRead,
690     asyncWrite,
691     asyncSeek,
692     asyncTruncate,
693     asyncSync,
694     asyncSetFullSync,
695     asyncFileHandle,
696     asyncFileSize,
697     asyncLock,
698     asyncUnlock,
699     asyncLockState,
700     asyncCheckReservedLock
701   };
702 
703   if( openForWriting && SQLITE_ASYNC_TWO_FILEHANDLES ){
704     int dummy;
705     rc = xOrigOpenReadWrite(zName, &pBaseWrite, &dummy);
706     if( rc!=SQLITE_OK ){
707       goto error_out;
708     }
709   }
710 
711   n = strlen(zName);
712   for(i=n-1; i>=0 && zName[i]!='/'; i--){}
713   p = (AsyncFile *)sqlite3OsMalloc(sizeof(AsyncFile) + n - i);
714   if( !p ){
715     rc = SQLITE_NOMEM;
716     goto error_out;
717   }
718   memset(p, 0, sizeof(AsyncFile));
719   p->zName = (char*)&p[1];
720   strcpy(p->zName, &zName[i+1]);
721   p->nName = n - i;
722   p->pMethod = &iomethod;
723   p->pBaseRead = pBaseRead;
724   p->pBaseWrite = pBaseWrite;
725 
726   *pFile = (OsFile *)p;
727   return SQLITE_OK;
728 
729 error_out:
730   assert(!p);
731   sqlite3OsClose(&pBaseRead);
732   sqlite3OsClose(&pBaseWrite);
733   *pFile = 0;
734   return rc;
735 }
736 
737 /*
738 ** The async-IO backends implementation of the three functions used to open
739 ** a file (xOpenExclusive, xOpenReadWrite and xOpenReadOnly). Most of the
740 ** work is done in function asyncOpenFile() - see above.
741 */
742 static int asyncOpenExclusive(const char *z, OsFile **ppFile, int delFlag){
743   int rc = asyncOpenFile(z, ppFile, 0, 0);
744   if( rc==SQLITE_OK ){
745     AsyncFile *pFile = (AsyncFile *)(*ppFile);
746     int nByte = strlen(z)+1;
747     i64 i = (i64)(delFlag);
748     rc = addNewAsyncWrite(pFile, ASYNC_OPENEXCLUSIVE, i, nByte, z);
749     if( rc!=SQLITE_OK ){
750       sqlite3OsFree(pFile);
751       *ppFile = 0;
752     }
753   }
754   if( rc==SQLITE_OK ){
755     incrOpenFileCount();
756   }
757   return rc;
758 }
759 static int asyncOpenReadOnly(const char *z, OsFile **ppFile){
760   OsFile *pBase = 0;
761   int rc = xOrigOpenReadOnly(z, &pBase);
762   if( rc==SQLITE_OK ){
763     rc = asyncOpenFile(z, ppFile, pBase, 0);
764   }
765   if( rc==SQLITE_OK ){
766     incrOpenFileCount();
767   }
768   return rc;
769 }
770 static int asyncOpenReadWrite(const char *z, OsFile **ppFile, int *pReadOnly){
771   OsFile *pBase = 0;
772   int rc = xOrigOpenReadWrite(z, &pBase, pReadOnly);
773   if( rc==SQLITE_OK ){
774     rc = asyncOpenFile(z, ppFile, pBase, (*pReadOnly ? 0 : 1));
775   }
776   if( rc==SQLITE_OK ){
777     incrOpenFileCount();
778   }
779   return rc;
780 }
781 
782 /*
783 ** Implementation of sqlite3OsDelete. Add an entry to the end of the
784 ** write-op queue to perform the delete.
785 */
786 static int asyncDelete(const char *z){
787   return addNewAsyncWrite(0, ASYNC_DELETE, 0, strlen(z)+1, z);
788 }
789 
790 /*
791 ** Implementation of sqlite3OsSyncDirectory. Add an entry to the end of the
792 ** write-op queue to perform the directory sync.
793 */
794 static int asyncSyncDirectory(const char *z){
795   return addNewAsyncWrite(0, ASYNC_SYNCDIRECTORY, 0, strlen(z)+1, z);
796 }
797 
798 /*
799 ** Implementation of sqlite3OsFileExists. Return true if file 'z' exists
800 ** in the file system.
801 **
802 ** This method holds the mutex from start to finish.
803 */
804 static int asyncFileExists(const char *z){
805   int ret;
806   AsyncWrite *p;
807 
808   pthread_mutex_lock(&async.queueMutex);
809 
810   /* See if the real file system contains the specified file.  */
811   ret = xOrigFileExists(z);
812 
813   for(p=async.pQueueFirst; p; p = p->pNext){
814     if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, z) ){
815       ret = 0;
816     }else if( p->op==ASYNC_OPENEXCLUSIVE && 0==strcmp(p->zBuf, z) ){
817       ret = 1;
818     }
819   }
820 
821   TRACE(("EXISTS: %s = %d\n", z, ret));
822   pthread_mutex_unlock(&async.queueMutex);
823   return ret;
824 }
825 
826 /*
827 ** Call this routine to enable or disable the
828 ** asynchronous IO features implemented in this file.
829 **
830 ** This routine is not even remotely threadsafe.  Do not call
831 ** this routine while any SQLite database connections are open.
832 */
833 static void asyncEnable(int enable){
834   if( enable && xOrigOpenReadWrite==0 ){
835     assert(sqlite3Os.xOpenReadWrite);
836     sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1);
837     xOrigOpenReadWrite = sqlite3Os.xOpenReadWrite;
838     xOrigOpenReadOnly = sqlite3Os.xOpenReadOnly;
839     xOrigOpenExclusive = sqlite3Os.xOpenExclusive;
840     xOrigDelete = sqlite3Os.xDelete;
841     xOrigFileExists = sqlite3Os.xFileExists;
842     xOrigSyncDirectory = sqlite3Os.xSyncDirectory;
843 
844     sqlite3Os.xOpenReadWrite = asyncOpenReadWrite;
845     sqlite3Os.xOpenReadOnly = asyncOpenReadOnly;
846     sqlite3Os.xOpenExclusive = asyncOpenExclusive;
847     sqlite3Os.xDelete = asyncDelete;
848     sqlite3Os.xFileExists = asyncFileExists;
849     sqlite3Os.xSyncDirectory = asyncSyncDirectory;
850     assert(sqlite3Os.xOpenReadWrite);
851   }
852   if( !enable && xOrigOpenReadWrite!=0 ){
853     assert(sqlite3Os.xOpenReadWrite);
854     sqlite3HashClear(&async.aLock);
855     sqlite3Os.xOpenReadWrite = xOrigOpenReadWrite;
856     sqlite3Os.xOpenReadOnly = xOrigOpenReadOnly;
857     sqlite3Os.xOpenExclusive = xOrigOpenExclusive;
858     sqlite3Os.xDelete = xOrigDelete;
859     sqlite3Os.xFileExists = xOrigFileExists;
860     sqlite3Os.xSyncDirectory = xOrigSyncDirectory;
861 
862     xOrigOpenReadWrite = 0;
863     xOrigOpenReadOnly = 0;
864     xOrigOpenExclusive = 0;
865     xOrigDelete = 0;
866     xOrigFileExists = 0;
867     xOrigSyncDirectory = 0;
868     assert(sqlite3Os.xOpenReadWrite);
869   }
870 }
871 
872 /*
873 ** This procedure runs in a separate thread, reading messages off of the
874 ** write queue and processing them one by one.
875 **
876 ** If async.writerHaltNow is true, then this procedure exits
877 ** after processing a single message.
878 **
879 ** If async.writerHaltWhenIdle is true, then this procedure exits when
880 ** the write queue is empty.
881 **
882 ** If both of the above variables are false, this procedure runs
883 ** indefinately, waiting for operations to be added to the write queue
884 ** and processing them in the order in which they arrive.
885 **
886 ** An artifical delay of async.ioDelay milliseconds is inserted before
887 ** each write operation in order to simulate the effect of a slow disk.
888 **
889 ** Only one instance of this procedure may be running at a time.
890 */
891 static void *asyncWriterThread(void *NotUsed){
892   AsyncWrite *p = 0;
893   int rc = SQLITE_OK;
894   int holdingMutex = 0;
895 
896   if( pthread_mutex_trylock(&async.writerMutex) ){
897     return 0;
898   }
899   while( async.writerHaltNow==0 ){
900     OsFile *pBase = 0;
901 
902     if( !holdingMutex ){
903       pthread_mutex_lock(&async.queueMutex);
904     }
905     while( (p = async.pQueueFirst)==0 ){
906       pthread_cond_broadcast(&async.emptySignal);
907       if( async.writerHaltWhenIdle ){
908         pthread_mutex_unlock(&async.queueMutex);
909         break;
910       }else{
911         TRACE(("IDLE\n"));
912         pthread_cond_wait(&async.queueSignal, &async.queueMutex);
913         TRACE(("WAKEUP\n"));
914       }
915     }
916     if( p==0 ) break;
917     holdingMutex = 1;
918 
919     /* Right now this thread is holding the mutex on the write-op queue.
920     ** Variable 'p' points to the first entry in the write-op queue. In
921     ** the general case, we hold on to the mutex for the entire body of
922     ** the loop.
923     **
924     ** However in the cases enumerated below, we relinquish the mutex,
925     ** perform the IO, and then re-request the mutex before removing 'p' from
926     ** the head of the write-op queue. The idea is to increase concurrency with
927     ** sqlite threads.
928     **
929     **     * An ASYNC_CLOSE operation.
930     **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish
931     **       the mutex, call the underlying xOpenExclusive() function, then
932     **       re-aquire the mutex before seting the AsyncFile.pBaseRead
933     **       variable.
934     **     * ASYNC_SYNC and ASYNC_WRITE operations, if
935     **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two
936     **       file-handles are open for the particular file being "synced".
937     */
938     if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){
939       p->op = ASYNC_NOOP;
940     }
941     if( p->pFile ){
942       pBase = p->pFile->pBaseWrite;
943       if(
944         p->op==ASYNC_CLOSE ||
945         p->op==ASYNC_OPENEXCLUSIVE ||
946         (pBase && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) )
947       ){
948         pthread_mutex_unlock(&async.queueMutex);
949         holdingMutex = 0;
950       }
951       if( !pBase ){
952         pBase = p->pFile->pBaseRead;
953       }
954     }
955 
956     switch( p->op ){
957       case ASYNC_NOOP:
958         break;
959 
960       case ASYNC_WRITE:
961         assert( pBase );
962         TRACE(("WRITE %s %d bytes at %d\n",
963                 p->pFile->zName, p->nByte, p->iOffset));
964         rc = sqlite3OsSeek(pBase, p->iOffset);
965         if( rc==SQLITE_OK ){
966           rc = sqlite3OsWrite(pBase, (const void *)(p->zBuf), p->nByte);
967         }
968         break;
969 
970       case ASYNC_SYNC:
971         assert( pBase );
972         TRACE(("SYNC %s\n", p->pFile->zName));
973         rc = sqlite3OsSync(pBase, p->nByte);
974         break;
975 
976       case ASYNC_TRUNCATE:
977         assert( pBase );
978         TRACE(("TRUNCATE %s to %d bytes\n", p->pFile->zName, p->iOffset));
979         rc = sqlite3OsTruncate(pBase, p->iOffset);
980         break;
981 
982       case ASYNC_CLOSE:
983         TRACE(("CLOSE %s\n", p->pFile->zName));
984         sqlite3OsClose(&p->pFile->pBaseWrite);
985         sqlite3OsClose(&p->pFile->pBaseRead);
986         sqlite3OsFree(p->pFile);
987         break;
988 
989       case ASYNC_OPENDIRECTORY:
990         assert( pBase );
991         TRACE(("OPENDIR %s\n", p->zBuf));
992         sqlite3OsOpenDirectory(pBase, p->zBuf);
993         break;
994 
995       case ASYNC_SETFULLSYNC:
996         assert( pBase );
997         TRACE(("SETFULLSYNC %s %d\n", p->pFile->zName, p->nByte));
998         sqlite3OsSetFullSync(pBase, p->nByte);
999         break;
1000 
1001       case ASYNC_DELETE:
1002         TRACE(("DELETE %s\n", p->zBuf));
1003         rc = xOrigDelete(p->zBuf);
1004         break;
1005 
1006       case ASYNC_SYNCDIRECTORY:
1007         TRACE(("SYNCDIR %s\n", p->zBuf));
1008         rc = xOrigSyncDirectory(p->zBuf);
1009         break;
1010 
1011       case ASYNC_OPENEXCLUSIVE: {
1012         AsyncFile *pFile = p->pFile;
1013         int delFlag = ((p->iOffset)?1:0);
1014         OsFile *pBase = 0;
1015         TRACE(("OPEN %s delFlag=%d\n", p->zBuf, delFlag));
1016         assert(pFile->pBaseRead==0 && pFile->pBaseWrite==0);
1017         rc = xOrigOpenExclusive(p->zBuf, &pBase, delFlag);
1018         assert( holdingMutex==0 );
1019         pthread_mutex_lock(&async.queueMutex);
1020         holdingMutex = 1;
1021         if( rc==SQLITE_OK ){
1022           pFile->pBaseRead = pBase;
1023         }
1024         break;
1025       }
1026 
1027       default: assert(!"Illegal value for AsyncWrite.op");
1028     }
1029 
1030     /* If we didn't hang on to the mutex during the IO op, obtain it now
1031     ** so that the AsyncWrite structure can be safely removed from the
1032     ** global write-op queue.
1033     */
1034     if( !holdingMutex ){
1035       pthread_mutex_lock(&async.queueMutex);
1036       holdingMutex = 1;
1037     }
1038     /* TRACE(("UNLINK %p\n", p)); */
1039     if( p==async.pQueueLast ){
1040       async.pQueueLast = 0;
1041     }
1042     async.pQueueFirst = p->pNext;
1043     sqlite3OsFree(p);
1044     assert( holdingMutex );
1045 
1046     /* An IO error has occured. We cannot report the error back to the
1047     ** connection that requested the I/O since the error happened
1048     ** asynchronously.  The connection has already moved on.  There
1049     ** really is nobody to report the error to.
1050     **
1051     ** The file for which the error occured may have been a database or
1052     ** journal file. Regardless, none of the currently queued operations
1053     ** associated with the same database should now be performed. Nor should
1054     ** any subsequently requested IO on either a database or journal file
1055     ** handle for the same database be accepted until the main database
1056     ** file handle has been closed and reopened.
1057     **
1058     ** Furthermore, no further IO should be queued or performed on any file
1059     ** handle associated with a database that may have been part of a
1060     ** multi-file transaction that included the database associated with
1061     ** the IO error (i.e. a database ATTACHed to the same handle at some
1062     ** point in time).
1063     */
1064     if( rc!=SQLITE_OK ){
1065       async.ioError = rc;
1066     }
1067 
1068     /* Drop the queue mutex before continuing to the next write operation
1069     ** in order to give other threads a chance to work with the write queue.
1070     */
1071     if( !async.pQueueFirst || !async.ioError ){
1072       sqlite3ApiExit(0, 0);
1073       pthread_mutex_unlock(&async.queueMutex);
1074       holdingMutex = 0;
1075       if( async.ioDelay>0 ){
1076         sqlite3OsSleep(async.ioDelay);
1077       }else{
1078         sched_yield();
1079       }
1080     }
1081   }
1082 
1083   pthread_mutex_unlock(&async.writerMutex);
1084   return 0;
1085 }
1086 
1087 /**************************************************************************
1088 ** The remaining code defines a Tcl interface for testing the asynchronous
1089 ** IO implementation in this file.
1090 **
1091 ** To adapt the code to a non-TCL environment, delete or comment out
1092 ** the code that follows.
1093 */
1094 
1095 /*
1096 ** sqlite3async_enable ?YES/NO?
1097 **
1098 ** Enable or disable the asynchronous I/O backend.  This command is
1099 ** not thread-safe.  Do not call it while any database connections
1100 ** are open.
1101 */
1102 static int testAsyncEnable(
1103   void * clientData,
1104   Tcl_Interp *interp,
1105   int objc,
1106   Tcl_Obj *CONST objv[]
1107 ){
1108   if( objc!=1 && objc!=2 ){
1109     Tcl_WrongNumArgs(interp, 1, objv, "?YES/NO?");
1110     return TCL_ERROR;
1111   }
1112   if( objc==1 ){
1113     Tcl_SetObjResult(interp, Tcl_NewBooleanObj(xOrigOpenReadWrite!=0));
1114   }else{
1115     int en;
1116     if( Tcl_GetBooleanFromObj(interp, objv[1], &en) ) return TCL_ERROR;
1117     asyncEnable(en);
1118   }
1119   return TCL_OK;
1120 }
1121 
1122 /*
1123 ** sqlite3async_halt  "now"|"idle"|"never"
1124 **
1125 ** Set the conditions at which the writer thread will halt.
1126 */
1127 static int testAsyncHalt(
1128   void * clientData,
1129   Tcl_Interp *interp,
1130   int objc,
1131   Tcl_Obj *CONST objv[]
1132 ){
1133   const char *zCond;
1134   if( objc!=2 ){
1135     Tcl_WrongNumArgs(interp, 1, objv, "\"now\"|\"idle\"|\"never\"");
1136     return TCL_ERROR;
1137   }
1138   zCond = Tcl_GetString(objv[1]);
1139   if( strcmp(zCond, "now")==0 ){
1140     async.writerHaltNow = 1;
1141     pthread_cond_broadcast(&async.queueSignal);
1142   }else if( strcmp(zCond, "idle")==0 ){
1143     async.writerHaltWhenIdle = 1;
1144     async.writerHaltNow = 0;
1145     pthread_cond_broadcast(&async.queueSignal);
1146   }else if( strcmp(zCond, "never")==0 ){
1147     async.writerHaltWhenIdle = 0;
1148     async.writerHaltNow = 0;
1149   }else{
1150     Tcl_AppendResult(interp,
1151       "should be one of: \"now\", \"idle\", or \"never\"", (char*)0);
1152     return TCL_ERROR;
1153   }
1154   return TCL_OK;
1155 }
1156 
1157 /*
1158 ** sqlite3async_delay ?MS?
1159 **
1160 ** Query or set the number of milliseconds of delay in the writer
1161 ** thread after each write operation.  The default is 0.  By increasing
1162 ** the memory delay we can simulate the effect of slow disk I/O.
1163 */
1164 static int testAsyncDelay(
1165   void * clientData,
1166   Tcl_Interp *interp,
1167   int objc,
1168   Tcl_Obj *CONST objv[]
1169 ){
1170   if( objc!=1 && objc!=2 ){
1171     Tcl_WrongNumArgs(interp, 1, objv, "?MS?");
1172     return TCL_ERROR;
1173   }
1174   if( objc==1 ){
1175     Tcl_SetObjResult(interp, Tcl_NewIntObj(async.ioDelay));
1176   }else{
1177     int ioDelay;
1178     if( Tcl_GetIntFromObj(interp, objv[1], &ioDelay) ) return TCL_ERROR;
1179     async.ioDelay = ioDelay;
1180   }
1181   return TCL_OK;
1182 }
1183 
1184 /*
1185 ** sqlite3async_start
1186 **
1187 ** Start a new writer thread.
1188 */
1189 static int testAsyncStart(
1190   void * clientData,
1191   Tcl_Interp *interp,
1192   int objc,
1193   Tcl_Obj *CONST objv[]
1194 ){
1195   pthread_t x;
1196   int rc;
1197   rc = pthread_create(&x, 0, asyncWriterThread, 0);
1198   if( rc ){
1199     Tcl_AppendResult(interp, "failed to create the thread", 0);
1200     return TCL_ERROR;
1201   }
1202   pthread_detach(x);
1203   return TCL_OK;
1204 }
1205 
1206 /*
1207 ** sqlite3async_wait
1208 **
1209 ** Wait for the current writer thread to terminate.
1210 **
1211 ** If the current writer thread is set to run forever then this
1212 ** command would block forever.  To prevent that, an error is returned.
1213 */
1214 static int testAsyncWait(
1215   void * clientData,
1216   Tcl_Interp *interp,
1217   int objc,
1218   Tcl_Obj *CONST objv[]
1219 ){
1220   int cnt = 10;
1221   if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){
1222     Tcl_AppendResult(interp, "would block forever", (char*)0);
1223     return TCL_ERROR;
1224   }
1225 
1226   while( cnt-- && !pthread_mutex_trylock(&async.writerMutex) ){
1227     pthread_mutex_unlock(&async.writerMutex);
1228     sched_yield();
1229   }
1230   if( cnt>=0 ){
1231     TRACE(("WAIT\n"));
1232     pthread_mutex_lock(&async.queueMutex);
1233     pthread_cond_broadcast(&async.queueSignal);
1234     pthread_mutex_unlock(&async.queueMutex);
1235     pthread_mutex_lock(&async.writerMutex);
1236     pthread_mutex_unlock(&async.writerMutex);
1237   }else{
1238     TRACE(("NO-WAIT\n"));
1239   }
1240   return TCL_OK;
1241 }
1242 
1243 
1244 #endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */
1245 
1246 /*
1247 ** This routine registers the custom TCL commands defined in this
1248 ** module.  This should be the only procedure visible from outside
1249 ** of this module.
1250 */
1251 int Sqlitetestasync_Init(Tcl_Interp *interp){
1252 #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO)
1253   Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0);
1254   Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0);
1255   Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0);
1256   Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);
1257   Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);
1258   Tcl_LinkVar(interp, "sqlite3async_trace",
1259       (char*)&sqlite3async_trace, TCL_LINK_INT);
1260 #endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */
1261   return TCL_OK;
1262 }
1263