Back to index

lightning-sunbird  0.9+nobinonly
test_async.c
Go to the documentation of this file.
00001 /*
00002 ** 2005 December 14
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 *************************************************************************
00012 **
00013 ** This file contains an example implementation of an asynchronous IO 
00014 ** backend for SQLite.
00015 **
00016 ** WHAT IS ASYNCHRONOUS I/O?
00017 **
00018 ** With asynchronous I/O, write requests are handled by a separate thread
00019 ** running in the background.  This means that the thread that initiates
00020 ** a database write does not have to wait for (sometimes slow) disk I/O
00021 ** to occur.  The write seems to happen very quickly, though in reality
00022 ** it is happening at its usual slow pace in the background.
00023 **
00024 ** Asynchronous I/O appears to give better responsiveness, but at a price.
00025 ** You lose the Durable property.  With the default I/O backend of SQLite,
00026 ** once a write completes, you know that the information you wrote is
00027 ** safely on disk.  With the asynchronous I/O, this is no the case.  If
00028 ** your program crashes or if you take a power lose after the database
00029 ** write but before the asynchronous write thread has completed, then the
00030 ** database change might never make it to disk and the next user of the
00031 ** database might not see your change.
00032 **
00033 ** You lose Durability with asynchronous I/O, but you still retain the
00034 ** other parts of ACID:  Atomic,  Consistent, and Isolated.  Many
00035 ** appliations get along fine without the Durablity.
00036 **
00037 ** HOW IT WORKS
00038 **
00039 ** Asynchronous I/O works by overloading the OS-layer disk I/O routines
00040 ** with modified versions that store the data to be written in queue of
00041 ** pending write operations.  Look at the asyncEnable() subroutine to see
00042 ** how overloading works.  Six os-layer routines are overloaded:
00043 **
00044 **     sqlite3OsOpenReadWrite;
00045 **     sqlite3OsOpenReadOnly;
00046 **     sqlite3OsOpenExclusive;
00047 **     sqlite3OsDelete;
00048 **     sqlite3OsFileExists;
00049 **     sqlite3OsSyncDirectory;
00050 **
00051 ** The original implementations of these routines are saved and are
00052 ** used by the writer thread to do the real I/O.  The substitute
00053 ** implementations typically put the I/O operation on a queue
00054 ** to be handled later by the writer thread, though read operations
00055 ** must be handled right away, obviously.
00056 **
00057 ** Asynchronous I/O is disabled by setting the os-layer interface routines
00058 ** back to their original values.
00059 **
00060 ** LIMITATIONS
00061 **
00062 ** This demonstration code is deliberately kept simple in order to keep
00063 ** the main ideas clear and easy to understand.  Real applications that
00064 ** want to do asynchronous I/O might want to add additional capabilities.
00065 ** For example, in this demonstration if writes are happening at a steady
00066 ** stream that exceeds the I/O capability of the background writer thread,
00067 ** the queue of pending write operations will grow without bound until we
00068 ** run out of memory.  Users of this technique may want to keep track of
00069 ** the quantity of pending writes and stop accepting new write requests
00070 ** when the buffer gets to be too big.
00071 */
00072 
00073 #include "sqliteInt.h"
00074 #include "os.h"
00075 #include <tcl.h>
00076 
00077 /* If the THREADSAFE macro is not set, assume that it is turned off. */
00078 #ifndef THREADSAFE
00079 # define THREADSAFE 0
00080 #endif
00081 
00082 /*
00083 ** This test uses pthreads and hence only works on unix and with
00084 ** a threadsafe build of SQLite.  It also requires that the redefinable
00085 ** I/O feature of SQLite be turned on.  This feature is turned off by
00086 ** default.  If a required element is missing, almost all of the code
00087 ** in this file is commented out.
00088 */
00089 #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO)
00090 
00091 /*
00092 ** This demo uses pthreads.  If you do not have a pthreads implementation
00093 ** for your operating system, you will need to recode the threading 
00094 ** logic.
00095 */
00096 #include <pthread.h>
00097 #include <sched.h>
00098 
00099 /* Useful macros used in several places */
00100 #define MIN(x,y) ((x)<(y)?(x):(y))
00101 #define MAX(x,y) ((x)>(y)?(x):(y))
00102 
00103 /* Forward references */
00104 typedef struct AsyncWrite AsyncWrite;
00105 typedef struct AsyncFile AsyncFile;
00106 
00107 /* Enable for debugging */
00108 static int sqlite3async_trace = 0;
00109 # define TRACE(X) if( sqlite3async_trace ) asyncTrace X
00110 static void asyncTrace(const char *zFormat, ...){
00111   char *z;
00112   va_list ap;
00113   va_start(ap, zFormat);
00114   z = sqlite3_vmprintf(zFormat, ap);
00115   va_end(ap);
00116   fprintf(stderr, "[%d] %s", (int)pthread_self(), z);
00117   free(z);
00118 }
00119 
00120 /*
00121 ** THREAD SAFETY NOTES
00122 **
00123 ** Basic rules:
00124 **
00125 **     * Both read and write access to the global write-op queue must be 
00126 **       protected by the async.queueMutex.
00127 **
00128 **     * The file handles from the underlying system are assumed not to 
00129 **       be thread safe.
00130 **
00131 **     * See the last two paragraphs under "The Writer Thread" for
00132 **       an assumption to do with file-handle synchronization by the Os.
00133 **
00134 ** File system operations (invoked by SQLite thread):
00135 **
00136 **     xOpenXXX (three versions)
00137 **     xDelete
00138 **     xFileExists
00139 **     xSyncDirectory
00140 **
00141 ** File handle operations (invoked by SQLite thread):
00142 **
00143 **         asyncWrite, asyncClose, asyncTruncate, asyncSync, 
00144 **         asyncSetFullSync, asyncOpenDirectory.
00145 **    
00146 **     The operations above add an entry to the global write-op list. They
00147 **     prepare the entry, acquire the async.queueMutex momentarily while
00148 **     list pointers are  manipulated to insert the new entry, then release
00149 **     the mutex and signal the writer thread to wake up in case it happens
00150 **     to be asleep.
00151 **
00152 **    
00153 **         asyncRead, asyncFileSize.
00154 **
00155 **     Read operations. Both of these read from both the underlying file
00156 **     first then adjust their result based on pending writes in the 
00157 **     write-op queue.   So async.queueMutex is held for the duration
00158 **     of these operations to prevent other threads from changing the
00159 **     queue in mid operation.
00160 **    
00161 **
00162 **         asyncLock, asyncUnlock, asyncLockState, asyncCheckReservedLock
00163 **    
00164 **     These primitives implement in-process locking using a hash table
00165 **     on the file name.  Files are locked correctly for connections coming
00166 **     from the same process.  But other processes cannot see these locks
00167 **     and will therefore not honor them.
00168 **
00169 **
00170 **         asyncFileHandle.
00171 **    
00172 **     The sqlite3OsFileHandle() function is currently only used when 
00173 **     debugging the pager module. Unless sqlite3OsClose() is called on the
00174 **     file (shouldn't be possible for other reasons), the underlying 
00175 **     implementations are safe to call without grabbing any mutex. So we just
00176 **     go ahead and call it no matter what any other threads are doing.
00177 **
00178 **    
00179 **         asyncSeek.
00180 **
00181 **     Calling this method just manipulates the AsyncFile.iOffset variable. 
00182 **     Since this variable is never accessed by writer thread, this
00183 **     function does not require the mutex.  Actual calls to OsSeek() take 
00184 **     place just before OsWrite() or OsRead(), which are always protected by 
00185 **     the mutex.
00186 **
00187 ** The writer thread:
00188 **
00189 **     The async.writerMutex is used to make sure only there is only
00190 **     a single writer thread running at a time.
00191 **
00192 **     Inside the writer thread is a loop that works like this:
00193 **
00194 **         WHILE (write-op list is not empty)
00195 **             Do IO operation at head of write-op list
00196 **             Remove entry from head of write-op list
00197 **         END WHILE
00198 **
00199 **     The async.queueMutex is always held during the <write-op list is 
00200 **     not empty> test, and when the entry is removed from the head
00201 **     of the write-op list. Sometimes it is held for the interim
00202 **     period (while the IO is performed), and sometimes it is
00203 **     relinquished. It is relinquished if (a) the IO op is an
00204 **     ASYNC_CLOSE or (b) when the file handle was opened, two of
00205 **     the underlying systems handles were opened on the same
00206 **     file-system entry.
00207 **
00208 **     If condition (b) above is true, then one file-handle 
00209 **     (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the
00210 **     file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush() 
00211 **     threads to perform write() operations. This means that read 
00212 **     operations are not blocked by asynchronous writes (although 
00213 **     asynchronous writes may still be blocked by reads).
00214 **
00215 **     This assumes that the OS keeps two handles open on the same file
00216 **     properly in sync. That is, any read operation that starts after a
00217 **     write operation on the same file system entry has completed returns
00218 **     data consistent with the write. We also assume that if one thread 
00219 **     reads a file while another is writing it all bytes other than the
00220 **     ones actually being written contain valid data.
00221 **
00222 **     If the above assumptions are not true, set the preprocessor symbol
00223 **     SQLITE_ASYNC_TWO_FILEHANDLES to 0.
00224 */
00225 
00226 #ifndef SQLITE_ASYNC_TWO_FILEHANDLES
00227 /* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */
00228 #define SQLITE_ASYNC_TWO_FILEHANDLES 1
00229 #endif
00230 
00231 /*
00232 ** State information is held in the static variable "async" defined
00233 ** as follows:
00234 */
00235 static struct TestAsyncStaticData {
00236   pthread_mutex_t queueMutex;  /* Mutex for access to write operation queue */
00237   pthread_mutex_t writerMutex; /* Prevents multiple writer threads */
00238   pthread_mutex_t lockMutex;   /* For access to aLock hash table */
00239   pthread_cond_t queueSignal;  /* For waking up sleeping writer thread */
00240   pthread_cond_t emptySignal;  /* Notify when the write queue is empty */
00241   AsyncWrite *pQueueFirst;     /* Next write operation to be processed */
00242   AsyncWrite *pQueueLast;      /* Last write operation on the list */
00243   Hash aLock;                  /* Files locked */
00244   volatile int ioDelay;             /* Extra delay between write operations */
00245   volatile int writerHaltWhenIdle;  /* Writer thread halts when queue empty */
00246   volatile int writerHaltNow;       /* Writer thread halts after next op */
00247   int ioError;                 /* True if an IO error has occured */
00248   int nFile;                   /* Number of open files (from sqlite pov) */
00249 } async = {
00250   PTHREAD_MUTEX_INITIALIZER,
00251   PTHREAD_MUTEX_INITIALIZER,
00252   PTHREAD_MUTEX_INITIALIZER,
00253   PTHREAD_COND_INITIALIZER,
00254   PTHREAD_COND_INITIALIZER,
00255 };
00256 
00257 /* Possible values of AsyncWrite.op */
00258 #define ASYNC_NOOP          0
00259 #define ASYNC_WRITE         1
00260 #define ASYNC_SYNC          2
00261 #define ASYNC_TRUNCATE      3
00262 #define ASYNC_CLOSE         4
00263 #define ASYNC_OPENDIRECTORY 5
00264 #define ASYNC_SETFULLSYNC   6
00265 #define ASYNC_DELETE        7
00266 #define ASYNC_OPENEXCLUSIVE 8
00267 #define ASYNC_SYNCDIRECTORY 9
00268 
00269 /* Names of opcodes.  Used for debugging only.
00270 ** Make sure these stay in sync with the macros above!
00271 */
00272 static const char *azOpcodeName[] = {
00273   "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE",
00274   "OPENDIR", "SETFULLSYNC", "DELETE", "OPENEX", "SYNCDIR",
00275 };
00276 
00277 /*
00278 ** Entries on the write-op queue are instances of the AsyncWrite
00279 ** structure, defined here.
00280 **
00281 ** The interpretation of the iOffset and nByte variables varies depending 
00282 ** on the value of AsyncWrite.op:
00283 **
00284 ** ASYNC_WRITE:
00285 **     iOffset -> Offset in file to write to.
00286 **     nByte   -> Number of bytes of data to write (pointed to by zBuf).
00287 **
00288 ** ASYNC_SYNC:
00289 **     iOffset -> Unused.
00290 **     nByte   -> Value of "fullsync" flag to pass to sqlite3OsSync().
00291 **
00292 ** ASYNC_TRUNCATE:
00293 **     iOffset -> Size to truncate file to.
00294 **     nByte   -> Unused.
00295 **
00296 ** ASYNC_CLOSE:
00297 **     iOffset -> Unused.
00298 **     nByte   -> Unused.
00299 **
00300 ** ASYNC_OPENDIRECTORY:
00301 **     iOffset -> Unused.
00302 **     nByte   -> Number of bytes of zBuf points to (directory name).
00303 **
00304 ** ASYNC_SETFULLSYNC:
00305 **     iOffset -> Unused.
00306 **     nByte   -> New value for the full-sync flag.
00307 **
00308 **
00309 ** ASYNC_DELETE:
00310 **     iOffset -> Unused.
00311 **     nByte   -> Number of bytes of zBuf points to (file name).
00312 **
00313 ** ASYNC_OPENEXCLUSIVE:
00314 **     iOffset -> Value of "delflag".
00315 **     nByte   -> Number of bytes of zBuf points to (file name).
00316 **
00317 **
00318 ** For an ASYNC_WRITE operation, zBuf points to the data to write to the file. 
00319 ** This space is sqliteMalloc()d along with the AsyncWrite structure in a
00320 ** single blob, so is deleted when sqliteFree() is called on the parent 
00321 ** structure.
00322 */
00323 struct AsyncWrite {
00324   AsyncFile *pFile;   /* File to write data to or sync */
00325   int op;             /* One of ASYNC_xxx etc. */
00326   i64 iOffset;        /* See above */
00327   int nByte;          /* See above */
00328   char *zBuf;         /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
00329   AsyncWrite *pNext;  /* Next write operation (to any file) */
00330 };
00331 
00332 /* 
00333 ** The AsyncFile structure is a subclass of OsFile used for asynchronous IO.
00334 */
00335 struct AsyncFile {
00336   IoMethod *pMethod;   /* Must be first */
00337   i64 iOffset;         /* Current seek() offset in file */
00338   char *zName;         /* Underlying OS filename - used for debugging */
00339   int nName;           /* Number of characters in zName */
00340   OsFile *pBaseRead;   /* Read handle to the underlying Os file */
00341   OsFile *pBaseWrite;  /* Write handle to the underlying Os file */
00342 };
00343 
00344 /*
00345 ** Add an entry to the end of the global write-op list. pWrite should point 
00346 ** to an AsyncWrite structure allocated using sqlite3OsMalloc().  The writer
00347 ** thread will call sqlite3OsFree() to free the structure after the specified
00348 ** operation has been completed.
00349 **
00350 ** Once an AsyncWrite structure has been added to the list, it becomes the
00351 ** property of the writer thread and must not be read or modified by the
00352 ** caller.  
00353 */
00354 static void addAsyncWrite(AsyncWrite *pWrite){
00355   /* We must hold the queue mutex in order to modify the queue pointers */
00356   pthread_mutex_lock(&async.queueMutex);
00357 
00358   /* Add the record to the end of the write-op queue */
00359   assert( !pWrite->pNext );
00360   if( async.pQueueLast ){
00361     assert( async.pQueueFirst );
00362     async.pQueueLast->pNext = pWrite;
00363   }else{
00364     async.pQueueFirst = pWrite;
00365   }
00366   async.pQueueLast = pWrite;
00367   TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op],
00368          pWrite->pFile ? pWrite->pFile->zName : "-", pWrite->iOffset));
00369 
00370   if( pWrite->op==ASYNC_CLOSE ){
00371     async.nFile--;
00372     if( async.nFile==0 ){
00373       async.ioError = SQLITE_OK;
00374     }
00375   }
00376 
00377   /* Drop the queue mutex */
00378   pthread_mutex_unlock(&async.queueMutex);
00379 
00380   /* The writer thread might have been idle because there was nothing
00381   ** on the write-op queue for it to do.  So wake it up. */
00382   pthread_cond_signal(&async.queueSignal);
00383 }
00384 
00385 /*
00386 ** Increment async.nFile in a thread-safe manner.
00387 */
00388 static void incrOpenFileCount(){
00389   /* We must hold the queue mutex in order to modify async.nFile */
00390   pthread_mutex_lock(&async.queueMutex);
00391   if( async.nFile==0 ){
00392     async.ioError = SQLITE_OK;
00393   }
00394   async.nFile++;
00395   pthread_mutex_unlock(&async.queueMutex);
00396 }
00397 
00398 /*
00399 ** This is a utility function to allocate and populate a new AsyncWrite
00400 ** structure and insert it (via addAsyncWrite() ) into the global list.
00401 */
00402 static int addNewAsyncWrite(
00403   AsyncFile *pFile, 
00404   int op, 
00405   i64 iOffset, 
00406   int nByte,
00407   const char *zByte
00408 ){
00409   AsyncWrite *p;
00410   if( op!=ASYNC_CLOSE && async.ioError ){
00411     return async.ioError;
00412   }
00413   p = sqlite3OsMalloc(sizeof(AsyncWrite) + (zByte?nByte:0));
00414   if( !p ){
00415     return SQLITE_NOMEM;
00416   }
00417   p->op = op;
00418   p->iOffset = iOffset;
00419   p->nByte = nByte;
00420   p->pFile = pFile;
00421   p->pNext = 0;
00422   if( zByte ){
00423     p->zBuf = (char *)&p[1];
00424     memcpy(p->zBuf, zByte, nByte);
00425   }else{
00426     p->zBuf = 0;
00427   }
00428   addAsyncWrite(p);
00429   return SQLITE_OK;
00430 }
00431 
00432 /*
00433 ** Close the file. This just adds an entry to the write-op list, the file is
00434 ** not actually closed.
00435 */
00436 static int asyncClose(OsFile **pId){
00437   return addNewAsyncWrite((AsyncFile *)*pId, ASYNC_CLOSE, 0, 0, 0);
00438 }
00439 
00440 /*
00441 ** Implementation of sqlite3OsWrite() for asynchronous files. Instead of 
00442 ** writing to the underlying file, this function adds an entry to the end of
00443 ** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
00444 ** returned.
00445 */
00446 static int asyncWrite(OsFile *id, const void *pBuf, int amt){
00447   AsyncFile *pFile = (AsyncFile *)id;
00448   int rc = addNewAsyncWrite(pFile, ASYNC_WRITE, pFile->iOffset, amt, pBuf);
00449   pFile->iOffset += (i64)amt;
00450   return rc;
00451 }
00452 
00453 /*
00454 ** Truncate the file to nByte bytes in length. This just adds an entry to 
00455 ** the write-op list, no IO actually takes place.
00456 */
00457 static int asyncTruncate(OsFile *id, i64 nByte){
00458   return addNewAsyncWrite((AsyncFile *)id, ASYNC_TRUNCATE, nByte, 0, 0);
00459 }
00460 
00461 /*
00462 ** Open the directory identified by zName and associate it with the 
00463 ** specified file. This just adds an entry to the write-op list, the 
00464 ** directory is opened later by sqlite3_async_flush().
00465 */
00466 static int asyncOpenDirectory(OsFile *id, const char *zName){
00467   AsyncFile *pFile = (AsyncFile *)id;
00468   return addNewAsyncWrite(pFile, ASYNC_OPENDIRECTORY, 0, strlen(zName)+1,zName);
00469 }
00470 
00471 /*
00472 ** Sync the file. This just adds an entry to the write-op list, the 
00473 ** sync() is done later by sqlite3_async_flush().
00474 */
00475 static int asyncSync(OsFile *id, int fullsync){
00476   return addNewAsyncWrite((AsyncFile *)id, ASYNC_SYNC, 0, fullsync, 0);
00477 }
00478 
00479 /*
00480 ** Set (or clear) the full-sync flag on the underlying file. This operation
00481 ** is queued and performed later by sqlite3_async_flush().
00482 */
00483 static void asyncSetFullSync(OsFile *id, int value){
00484   addNewAsyncWrite((AsyncFile *)id, ASYNC_SETFULLSYNC, 0, value, 0);
00485 }
00486 
00487 /*
00488 ** Read data from the file. First we read from the filesystem, then adjust 
00489 ** the contents of the buffer based on ASYNC_WRITE operations in the 
00490 ** write-op queue.
00491 **
00492 ** This method holds the mutex from start to finish.
00493 */
00494 static int asyncRead(OsFile *id, void *obuf, int amt){
00495   int rc = SQLITE_OK;
00496   i64 filesize;
00497   int nRead;
00498   AsyncFile *pFile = (AsyncFile *)id;
00499   OsFile *pBase = pFile->pBaseRead;
00500 
00501   /* If an I/O error has previously occurred on this file, then all
00502   ** subsequent operations fail.
00503   */
00504   if( async.ioError!=SQLITE_OK ){
00505     return async.ioError;
00506   }
00507 
00508   /* Grab the write queue mutex for the duration of the call */
00509   pthread_mutex_lock(&async.queueMutex);
00510 
00511   if( pBase ){
00512     rc = sqlite3OsFileSize(pBase, &filesize);
00513     if( rc!=SQLITE_OK ){
00514       goto asyncread_out;
00515     }
00516     rc = sqlite3OsSeek(pBase, pFile->iOffset);
00517     if( rc!=SQLITE_OK ){
00518       goto asyncread_out;
00519     }
00520     nRead = MIN(filesize - pFile->iOffset, amt);
00521     if( nRead>0 ){
00522       rc = sqlite3OsRead(pBase, obuf, nRead);
00523       TRACE(("READ %s %d bytes at %d\n", pFile->zName, nRead, pFile->iOffset));
00524     }
00525   }
00526 
00527   if( rc==SQLITE_OK ){
00528     AsyncWrite *p;
00529     i64 iOffset = pFile->iOffset;           /* Current seek offset */
00530 
00531     for(p=async.pQueueFirst; p; p = p->pNext){
00532       if( p->pFile==pFile && p->op==ASYNC_WRITE ){
00533         int iBeginOut = (p->iOffset - iOffset);
00534         int iBeginIn = -iBeginOut;
00535         int nCopy;
00536 
00537         if( iBeginIn<0 ) iBeginIn = 0;
00538         if( iBeginOut<0 ) iBeginOut = 0;
00539         nCopy = MIN(p->nByte-iBeginIn, amt-iBeginOut);
00540 
00541         if( nCopy>0 ){
00542           memcpy(&((char *)obuf)[iBeginOut], &p->zBuf[iBeginIn], nCopy);
00543           TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset));
00544         }
00545       }
00546     }
00547 
00548     pFile->iOffset += (i64)amt;
00549   }
00550 
00551 asyncread_out:
00552   pthread_mutex_unlock(&async.queueMutex);
00553   return rc;
00554 }
00555 
00556 /*
00557 ** Seek to the specified offset. This just adjusts the AsyncFile.iOffset 
00558 ** variable - calling seek() on the underlying file is defered until the 
00559 ** next read() or write() operation. 
00560 */
00561 static int asyncSeek(OsFile *id, i64 offset){
00562   AsyncFile *pFile = (AsyncFile *)id;
00563   pFile->iOffset = offset;
00564   return SQLITE_OK;
00565 }
00566 
00567 /*
00568 ** Read the size of the file. First we read the size of the file system 
00569 ** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations 
00570 ** currently in the write-op list. 
00571 **
00572 ** This method holds the mutex from start to finish.
00573 */
00574 int asyncFileSize(OsFile *id, i64 *pSize){
00575   int rc = SQLITE_OK;
00576   i64 s = 0;
00577   OsFile *pBase;
00578 
00579   pthread_mutex_lock(&async.queueMutex);
00580 
00581   /* Read the filesystem size from the base file. If pBaseRead is NULL, this
00582   ** means the file hasn't been opened yet. In this case all relevant data 
00583   ** must be in the write-op queue anyway, so we can omit reading from the
00584   ** file-system.
00585   */
00586   pBase = ((AsyncFile *)id)->pBaseRead;
00587   if( pBase ){
00588     rc = sqlite3OsFileSize(pBase, &s);
00589   }
00590 
00591   if( rc==SQLITE_OK ){
00592     AsyncWrite *p;
00593     for(p=async.pQueueFirst; p; p = p->pNext){
00594       if( p->pFile==(AsyncFile *)id ){
00595         switch( p->op ){
00596           case ASYNC_WRITE:
00597             s = MAX(p->iOffset + (i64)(p->nByte), s);
00598             break;
00599           case ASYNC_TRUNCATE:
00600             s = MIN(s, p->iOffset);
00601             break;
00602         }
00603       }
00604     }
00605     *pSize = s;
00606   }
00607   pthread_mutex_unlock(&async.queueMutex);
00608   return rc;
00609 }
00610 
00611 /*
00612 ** Return the operating system file handle. This is only used for debugging 
00613 ** at the moment anyway.
00614 */
00615 static int asyncFileHandle(OsFile *id){
00616   return sqlite3OsFileHandle(((AsyncFile *)id)->pBaseRead);
00617 }
00618 
00619 /*
00620 ** No disk locking is performed.  We keep track of locks locally in
00621 ** the async.aLock hash table.  Locking should appear to work the same
00622 ** as with standard (unmodified) SQLite as long as all connections 
00623 ** come from this one process.  Connections from external processes
00624 ** cannot see our internal hash table (obviously) and will thus not
00625 ** honor our locks.
00626 */
00627 static int asyncLock(OsFile *id, int lockType){
00628   AsyncFile *pFile = (AsyncFile*)id;
00629   TRACE(("LOCK %d (%s)\n", lockType, pFile->zName));
00630   pthread_mutex_lock(&async.lockMutex);
00631   sqlite3HashInsert(&async.aLock, pFile->zName, pFile->nName, (void*)lockType);
00632   pthread_mutex_unlock(&async.lockMutex);
00633   return SQLITE_OK;
00634 }
00635 static int asyncUnlock(OsFile *id, int lockType){
00636   return asyncLock(id, lockType);
00637 }
00638 
00639 /*
00640 ** This function is called when the pager layer first opens a database file
00641 ** and is checking for a hot-journal.
00642 */
00643 static int asyncCheckReservedLock(OsFile *id){
00644   AsyncFile *pFile = (AsyncFile*)id;
00645   int rc;
00646   pthread_mutex_lock(&async.lockMutex);
00647   rc = (int)sqlite3HashFind(&async.aLock, pFile->zName, pFile->nName);
00648   pthread_mutex_unlock(&async.lockMutex);
00649   TRACE(("CHECK-LOCK %d (%s)\n", rc, pFile->zName));
00650   return rc>SHARED_LOCK;
00651 }
00652 
00653 /* 
00654 ** This is broken. But sqlite3OsLockState() is only used for testing anyway.
00655 */
00656 static int asyncLockState(OsFile *id){
00657   return SQLITE_OK;
00658 }
00659 
00660 /*
00661 ** The following variables hold pointers to the original versions of
00662 ** OS-layer interface routines that are overloaded in order to create
00663 ** the asynchronous I/O backend.
00664 */
00665 static int (*xOrigOpenReadWrite)(const char*, OsFile**, int*) = 0;
00666 static int (*xOrigOpenExclusive)(const char*, OsFile**, int) = 0;
00667 static int (*xOrigOpenReadOnly)(const char*, OsFile**) = 0;
00668 static int (*xOrigDelete)(const char*) = 0;
00669 static int (*xOrigFileExists)(const char*) = 0;
00670 static int (*xOrigSyncDirectory)(const char*) = 0;
00671 
00672 /*
00673 ** This routine does most of the work of opening a file and building
00674 ** the OsFile structure.
00675 */
00676 static int asyncOpenFile(
00677   const char *zName,     /* The name of the file to be opened */
00678   OsFile **pFile,        /* Put the OsFile structure here */
00679   OsFile *pBaseRead,     /* The real OsFile from the real I/O routine */
00680   int openForWriting     /* Open a second file handle for writing if true */
00681 ){
00682   int rc, i, n;
00683   AsyncFile *p;
00684   OsFile *pBaseWrite = 0;
00685 
00686   static IoMethod iomethod = {
00687     asyncClose,
00688     asyncOpenDirectory,
00689     asyncRead,
00690     asyncWrite,
00691     asyncSeek,
00692     asyncTruncate,
00693     asyncSync,
00694     asyncSetFullSync,
00695     asyncFileHandle,
00696     asyncFileSize,
00697     asyncLock,
00698     asyncUnlock,
00699     asyncLockState,
00700     asyncCheckReservedLock
00701   };
00702 
00703   if( openForWriting && SQLITE_ASYNC_TWO_FILEHANDLES ){
00704     int dummy;
00705     rc = xOrigOpenReadWrite(zName, &pBaseWrite, &dummy);
00706     if( rc!=SQLITE_OK ){
00707       goto error_out;
00708     }
00709   }
00710 
00711   n = strlen(zName);
00712   for(i=n-1; i>=0 && zName[i]!='/'; i--){}
00713   p = (AsyncFile *)sqlite3OsMalloc(sizeof(AsyncFile) + n - i);
00714   if( !p ){
00715     rc = SQLITE_NOMEM;
00716     goto error_out;
00717   }
00718   memset(p, 0, sizeof(AsyncFile));
00719   p->zName = (char*)&p[1];
00720   strcpy(p->zName, &zName[i+1]);
00721   p->nName = n - i;
00722   p->pMethod = &iomethod;
00723   p->pBaseRead = pBaseRead;
00724   p->pBaseWrite = pBaseWrite;
00725   
00726   *pFile = (OsFile *)p;
00727   return SQLITE_OK;
00728 
00729 error_out:
00730   assert(!p);
00731   sqlite3OsClose(&pBaseRead);
00732   sqlite3OsClose(&pBaseWrite);
00733   *pFile = 0;
00734   return rc;
00735 }
00736 
00737 /*
00738 ** The async-IO backends implementation of the three functions used to open
00739 ** a file (xOpenExclusive, xOpenReadWrite and xOpenReadOnly). Most of the 
00740 ** work is done in function asyncOpenFile() - see above.
00741 */
00742 static int asyncOpenExclusive(const char *z, OsFile **ppFile, int delFlag){
00743   int rc = asyncOpenFile(z, ppFile, 0, 0);
00744   if( rc==SQLITE_OK ){
00745     AsyncFile *pFile = (AsyncFile *)(*ppFile);
00746     int nByte = strlen(z)+1;
00747     i64 i = (i64)(delFlag);
00748     rc = addNewAsyncWrite(pFile, ASYNC_OPENEXCLUSIVE, i, nByte, z);
00749     if( rc!=SQLITE_OK ){
00750       sqlite3OsFree(pFile);
00751       *ppFile = 0;
00752     }
00753   }
00754   if( rc==SQLITE_OK ){
00755     incrOpenFileCount();
00756   }
00757   return rc;
00758 }
00759 static int asyncOpenReadOnly(const char *z, OsFile **ppFile){
00760   OsFile *pBase = 0;
00761   int rc = xOrigOpenReadOnly(z, &pBase);
00762   if( rc==SQLITE_OK ){
00763     rc = asyncOpenFile(z, ppFile, pBase, 0);
00764   }
00765   if( rc==SQLITE_OK ){
00766     incrOpenFileCount();
00767   }
00768   return rc;
00769 }
00770 static int asyncOpenReadWrite(const char *z, OsFile **ppFile, int *pReadOnly){
00771   OsFile *pBase = 0;
00772   int rc = xOrigOpenReadWrite(z, &pBase, pReadOnly);
00773   if( rc==SQLITE_OK ){
00774     rc = asyncOpenFile(z, ppFile, pBase, (*pReadOnly ? 0 : 1));
00775   }
00776   if( rc==SQLITE_OK ){
00777     incrOpenFileCount();
00778   }
00779   return rc;
00780 }
00781 
00782 /*
00783 ** Implementation of sqlite3OsDelete. Add an entry to the end of the 
00784 ** write-op queue to perform the delete.
00785 */
00786 static int asyncDelete(const char *z){
00787   return addNewAsyncWrite(0, ASYNC_DELETE, 0, strlen(z)+1, z);
00788 }
00789 
00790 /*
00791 ** Implementation of sqlite3OsSyncDirectory. Add an entry to the end of the 
00792 ** write-op queue to perform the directory sync.
00793 */
00794 static int asyncSyncDirectory(const char *z){
00795   return addNewAsyncWrite(0, ASYNC_SYNCDIRECTORY, 0, strlen(z)+1, z);
00796 }
00797 
00798 /*
00799 ** Implementation of sqlite3OsFileExists. Return true if file 'z' exists
00800 ** in the file system. 
00801 **
00802 ** This method holds the mutex from start to finish.
00803 */
00804 static int asyncFileExists(const char *z){
00805   int ret;
00806   AsyncWrite *p;
00807 
00808   pthread_mutex_lock(&async.queueMutex);
00809 
00810   /* See if the real file system contains the specified file.  */
00811   ret = xOrigFileExists(z);
00812   
00813   for(p=async.pQueueFirst; p; p = p->pNext){
00814     if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, z) ){
00815       ret = 0;
00816     }else if( p->op==ASYNC_OPENEXCLUSIVE && 0==strcmp(p->zBuf, z) ){
00817       ret = 1;
00818     }
00819   }
00820 
00821   TRACE(("EXISTS: %s = %d\n", z, ret));
00822   pthread_mutex_unlock(&async.queueMutex);
00823   return ret;
00824 }
00825 
00826 /*
00827 ** Call this routine to enable or disable the
00828 ** asynchronous IO features implemented in this file. 
00829 **
00830 ** This routine is not even remotely threadsafe.  Do not call
00831 ** this routine while any SQLite database connections are open.
00832 */
00833 static void asyncEnable(int enable){
00834   if( enable && xOrigOpenReadWrite==0 ){
00835     assert(sqlite3Os.xOpenReadWrite);
00836     sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1);
00837     xOrigOpenReadWrite = sqlite3Os.xOpenReadWrite;
00838     xOrigOpenReadOnly = sqlite3Os.xOpenReadOnly;
00839     xOrigOpenExclusive = sqlite3Os.xOpenExclusive;
00840     xOrigDelete = sqlite3Os.xDelete;
00841     xOrigFileExists = sqlite3Os.xFileExists;
00842     xOrigSyncDirectory = sqlite3Os.xSyncDirectory;
00843 
00844     sqlite3Os.xOpenReadWrite = asyncOpenReadWrite;
00845     sqlite3Os.xOpenReadOnly = asyncOpenReadOnly;
00846     sqlite3Os.xOpenExclusive = asyncOpenExclusive;
00847     sqlite3Os.xDelete = asyncDelete;
00848     sqlite3Os.xFileExists = asyncFileExists;
00849     sqlite3Os.xSyncDirectory = asyncSyncDirectory;
00850     assert(sqlite3Os.xOpenReadWrite);
00851   }
00852   if( !enable && xOrigOpenReadWrite!=0 ){
00853     assert(sqlite3Os.xOpenReadWrite);
00854     sqlite3HashClear(&async.aLock);
00855     sqlite3Os.xOpenReadWrite = xOrigOpenReadWrite;
00856     sqlite3Os.xOpenReadOnly = xOrigOpenReadOnly;
00857     sqlite3Os.xOpenExclusive = xOrigOpenExclusive;
00858     sqlite3Os.xDelete = xOrigDelete;
00859     sqlite3Os.xFileExists = xOrigFileExists;
00860     sqlite3Os.xSyncDirectory = xOrigSyncDirectory;
00861 
00862     xOrigOpenReadWrite = 0;
00863     xOrigOpenReadOnly = 0;
00864     xOrigOpenExclusive = 0;
00865     xOrigDelete = 0;
00866     xOrigFileExists = 0;
00867     xOrigSyncDirectory = 0;
00868     assert(sqlite3Os.xOpenReadWrite);
00869   }
00870 }
00871 
00872 /* 
00873 ** This procedure runs in a separate thread, reading messages off of the
00874 ** write queue and processing them one by one.  
00875 **
00876 ** If async.writerHaltNow is true, then this procedure exits
00877 ** after processing a single message.
00878 **
00879 ** If async.writerHaltWhenIdle is true, then this procedure exits when
00880 ** the write queue is empty.
00881 **
00882 ** If both of the above variables are false, this procedure runs
00883 ** indefinately, waiting for operations to be added to the write queue
00884 ** and processing them in the order in which they arrive.
00885 **
00886 ** An artifical delay of async.ioDelay milliseconds is inserted before
00887 ** each write operation in order to simulate the effect of a slow disk.
00888 **
00889 ** Only one instance of this procedure may be running at a time.
00890 */
00891 static void *asyncWriterThread(void *NotUsed){
00892   AsyncWrite *p = 0;
00893   int rc = SQLITE_OK;
00894   int holdingMutex = 0;
00895 
00896   if( pthread_mutex_trylock(&async.writerMutex) ){
00897     return 0;
00898   }
00899   while( async.writerHaltNow==0 ){
00900     OsFile *pBase = 0;
00901 
00902     if( !holdingMutex ){
00903       pthread_mutex_lock(&async.queueMutex);
00904     }
00905     while( (p = async.pQueueFirst)==0 ){
00906       pthread_cond_broadcast(&async.emptySignal);
00907       if( async.writerHaltWhenIdle ){
00908         pthread_mutex_unlock(&async.queueMutex);
00909         break;
00910       }else{
00911         TRACE(("IDLE\n"));
00912         pthread_cond_wait(&async.queueSignal, &async.queueMutex);
00913         TRACE(("WAKEUP\n"));
00914       }
00915     }
00916     if( p==0 ) break;
00917     holdingMutex = 1;
00918 
00919     /* Right now this thread is holding the mutex on the write-op queue.
00920     ** Variable 'p' points to the first entry in the write-op queue. In
00921     ** the general case, we hold on to the mutex for the entire body of
00922     ** the loop. 
00923     **
00924     ** However in the cases enumerated below, we relinquish the mutex,
00925     ** perform the IO, and then re-request the mutex before removing 'p' from
00926     ** the head of the write-op queue. The idea is to increase concurrency with
00927     ** sqlite threads.
00928     **
00929     **     * An ASYNC_CLOSE operation.
00930     **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish 
00931     **       the mutex, call the underlying xOpenExclusive() function, then
00932     **       re-aquire the mutex before seting the AsyncFile.pBaseRead 
00933     **       variable.
00934     **     * ASYNC_SYNC and ASYNC_WRITE operations, if 
00935     **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two
00936     **       file-handles are open for the particular file being "synced".
00937     */
00938     if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){
00939       p->op = ASYNC_NOOP;
00940     }
00941     if( p->pFile ){
00942       pBase = p->pFile->pBaseWrite;
00943       if( 
00944         p->op==ASYNC_CLOSE || 
00945         p->op==ASYNC_OPENEXCLUSIVE ||
00946         (pBase && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) ) 
00947       ){
00948         pthread_mutex_unlock(&async.queueMutex);
00949         holdingMutex = 0;
00950       }
00951       if( !pBase ){
00952         pBase = p->pFile->pBaseRead;
00953       }
00954     }
00955 
00956     switch( p->op ){
00957       case ASYNC_NOOP:
00958         break;
00959 
00960       case ASYNC_WRITE:
00961         assert( pBase );
00962         TRACE(("WRITE %s %d bytes at %d\n",
00963                 p->pFile->zName, p->nByte, p->iOffset));
00964         rc = sqlite3OsSeek(pBase, p->iOffset);
00965         if( rc==SQLITE_OK ){
00966           rc = sqlite3OsWrite(pBase, (const void *)(p->zBuf), p->nByte);
00967         }
00968         break;
00969 
00970       case ASYNC_SYNC:
00971         assert( pBase );
00972         TRACE(("SYNC %s\n", p->pFile->zName));
00973         rc = sqlite3OsSync(pBase, p->nByte);
00974         break;
00975 
00976       case ASYNC_TRUNCATE:
00977         assert( pBase );
00978         TRACE(("TRUNCATE %s to %d bytes\n", p->pFile->zName, p->iOffset));
00979         rc = sqlite3OsTruncate(pBase, p->iOffset);
00980         break;
00981 
00982       case ASYNC_CLOSE:
00983         TRACE(("CLOSE %s\n", p->pFile->zName));
00984         sqlite3OsClose(&p->pFile->pBaseWrite);
00985         sqlite3OsClose(&p->pFile->pBaseRead);
00986         sqlite3OsFree(p->pFile);
00987         break;
00988 
00989       case ASYNC_OPENDIRECTORY:
00990         assert( pBase );
00991         TRACE(("OPENDIR %s\n", p->zBuf));
00992         sqlite3OsOpenDirectory(pBase, p->zBuf);
00993         break;
00994 
00995       case ASYNC_SETFULLSYNC:
00996         assert( pBase );
00997         TRACE(("SETFULLSYNC %s %d\n", p->pFile->zName, p->nByte));
00998         sqlite3OsSetFullSync(pBase, p->nByte);
00999         break;
01000 
01001       case ASYNC_DELETE:
01002         TRACE(("DELETE %s\n", p->zBuf));
01003         rc = xOrigDelete(p->zBuf);
01004         break;
01005 
01006       case ASYNC_SYNCDIRECTORY:
01007         TRACE(("SYNCDIR %s\n", p->zBuf));
01008         rc = xOrigSyncDirectory(p->zBuf);
01009         break;
01010 
01011       case ASYNC_OPENEXCLUSIVE: {
01012         AsyncFile *pFile = p->pFile;
01013         int delFlag = ((p->iOffset)?1:0);
01014         OsFile *pBase = 0;
01015         TRACE(("OPEN %s delFlag=%d\n", p->zBuf, delFlag));
01016         assert(pFile->pBaseRead==0 && pFile->pBaseWrite==0);
01017         rc = xOrigOpenExclusive(p->zBuf, &pBase, delFlag);
01018         assert( holdingMutex==0 );
01019         pthread_mutex_lock(&async.queueMutex);
01020         holdingMutex = 1;
01021         if( rc==SQLITE_OK ){
01022           pFile->pBaseRead = pBase;
01023         }
01024         break;
01025       }
01026 
01027       default: assert(!"Illegal value for AsyncWrite.op");
01028     }
01029 
01030     /* If we didn't hang on to the mutex during the IO op, obtain it now
01031     ** so that the AsyncWrite structure can be safely removed from the 
01032     ** global write-op queue.
01033     */
01034     if( !holdingMutex ){
01035       pthread_mutex_lock(&async.queueMutex);
01036       holdingMutex = 1;
01037     }
01038     /* TRACE(("UNLINK %p\n", p)); */
01039     if( p==async.pQueueLast ){
01040       async.pQueueLast = 0;
01041     }
01042     async.pQueueFirst = p->pNext;
01043     sqlite3OsFree(p);
01044     assert( holdingMutex );
01045 
01046     /* An IO error has occured. We cannot report the error back to the
01047     ** connection that requested the I/O since the error happened 
01048     ** asynchronously.  The connection has already moved on.  There 
01049     ** really is nobody to report the error to.
01050     **
01051     ** The file for which the error occured may have been a database or
01052     ** journal file. Regardless, none of the currently queued operations
01053     ** associated with the same database should now be performed. Nor should
01054     ** any subsequently requested IO on either a database or journal file 
01055     ** handle for the same database be accepted until the main database
01056     ** file handle has been closed and reopened.
01057     **
01058     ** Furthermore, no further IO should be queued or performed on any file
01059     ** handle associated with a database that may have been part of a 
01060     ** multi-file transaction that included the database associated with 
01061     ** the IO error (i.e. a database ATTACHed to the same handle at some 
01062     ** point in time).
01063     */
01064     if( rc!=SQLITE_OK ){
01065       async.ioError = rc;
01066     }
01067 
01068     /* Drop the queue mutex before continuing to the next write operation
01069     ** in order to give other threads a chance to work with the write queue.
01070     */
01071     if( !async.pQueueFirst || !async.ioError ){
01072       sqlite3ApiExit(0, 0);
01073       pthread_mutex_unlock(&async.queueMutex);
01074       holdingMutex = 0;
01075       if( async.ioDelay>0 ){
01076         sqlite3OsSleep(async.ioDelay);
01077       }else{
01078         sched_yield();
01079       }
01080     }
01081   }
01082   
01083   pthread_mutex_unlock(&async.writerMutex);
01084   return 0;
01085 }
01086 
01087 /**************************************************************************
01088 ** The remaining code defines a Tcl interface for testing the asynchronous
01089 ** IO implementation in this file.
01090 **
01091 ** To adapt the code to a non-TCL environment, delete or comment out
01092 ** the code that follows.
01093 */
01094 
01095 /*
01096 ** sqlite3async_enable ?YES/NO?
01097 **
01098 ** Enable or disable the asynchronous I/O backend.  This command is
01099 ** not thread-safe.  Do not call it while any database connections
01100 ** are open.
01101 */
01102 static int testAsyncEnable(
01103   void * clientData,
01104   Tcl_Interp *interp,
01105   int objc,
01106   Tcl_Obj *CONST objv[]
01107 ){
01108   if( objc!=1 && objc!=2 ){
01109     Tcl_WrongNumArgs(interp, 1, objv, "?YES/NO?");
01110     return TCL_ERROR;
01111   }
01112   if( objc==1 ){
01113     Tcl_SetObjResult(interp, Tcl_NewBooleanObj(xOrigOpenReadWrite!=0));
01114   }else{
01115     int en;
01116     if( Tcl_GetBooleanFromObj(interp, objv[1], &en) ) return TCL_ERROR;
01117     asyncEnable(en);
01118   }
01119   return TCL_OK;
01120 }
01121 
01122 /*
01123 ** sqlite3async_halt  "now"|"idle"|"never"
01124 **
01125 ** Set the conditions at which the writer thread will halt.
01126 */
01127 static int testAsyncHalt(
01128   void * clientData,
01129   Tcl_Interp *interp,
01130   int objc,
01131   Tcl_Obj *CONST objv[]
01132 ){
01133   const char *zCond;
01134   if( objc!=2 ){
01135     Tcl_WrongNumArgs(interp, 1, objv, "\"now\"|\"idle\"|\"never\"");
01136     return TCL_ERROR;
01137   }
01138   zCond = Tcl_GetString(objv[1]);
01139   if( strcmp(zCond, "now")==0 ){
01140     async.writerHaltNow = 1;
01141     pthread_cond_broadcast(&async.queueSignal);
01142   }else if( strcmp(zCond, "idle")==0 ){
01143     async.writerHaltWhenIdle = 1;
01144     async.writerHaltNow = 0;
01145     pthread_cond_broadcast(&async.queueSignal);
01146   }else if( strcmp(zCond, "never")==0 ){
01147     async.writerHaltWhenIdle = 0;
01148     async.writerHaltNow = 0;
01149   }else{
01150     Tcl_AppendResult(interp, 
01151       "should be one of: \"now\", \"idle\", or \"never\"", (char*)0);
01152     return TCL_ERROR;
01153   }
01154   return TCL_OK;
01155 }
01156 
01157 /*
01158 ** sqlite3async_delay ?MS?
01159 **
01160 ** Query or set the number of milliseconds of delay in the writer
01161 ** thread after each write operation.  The default is 0.  By increasing
01162 ** the memory delay we can simulate the effect of slow disk I/O.
01163 */
01164 static int testAsyncDelay(
01165   void * clientData,
01166   Tcl_Interp *interp,
01167   int objc,
01168   Tcl_Obj *CONST objv[]
01169 ){
01170   if( objc!=1 && objc!=2 ){
01171     Tcl_WrongNumArgs(interp, 1, objv, "?MS?");
01172     return TCL_ERROR;
01173   }
01174   if( objc==1 ){
01175     Tcl_SetObjResult(interp, Tcl_NewIntObj(async.ioDelay));
01176   }else{
01177     int ioDelay;
01178     if( Tcl_GetIntFromObj(interp, objv[1], &ioDelay) ) return TCL_ERROR;
01179     async.ioDelay = ioDelay;
01180   }
01181   return TCL_OK;
01182 }
01183 
01184 /*
01185 ** sqlite3async_start
01186 **
01187 ** Start a new writer thread.
01188 */
01189 static int testAsyncStart(
01190   void * clientData,
01191   Tcl_Interp *interp,
01192   int objc,
01193   Tcl_Obj *CONST objv[]
01194 ){
01195   pthread_t x;
01196   int rc;
01197   rc = pthread_create(&x, 0, asyncWriterThread, 0);
01198   if( rc ){
01199     Tcl_AppendResult(interp, "failed to create the thread", 0);
01200     return TCL_ERROR;
01201   }
01202   pthread_detach(x);
01203   return TCL_OK;
01204 }
01205 
01206 /*
01207 ** sqlite3async_wait
01208 **
01209 ** Wait for the current writer thread to terminate.
01210 **
01211 ** If the current writer thread is set to run forever then this
01212 ** command would block forever.  To prevent that, an error is returned. 
01213 */
01214 static int testAsyncWait(
01215   void * clientData,
01216   Tcl_Interp *interp,
01217   int objc,
01218   Tcl_Obj *CONST objv[]
01219 ){
01220   int cnt = 10;
01221   if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){
01222     Tcl_AppendResult(interp, "would block forever", (char*)0);
01223     return TCL_ERROR;
01224   }
01225 
01226   while( cnt-- && !pthread_mutex_trylock(&async.writerMutex) ){
01227     pthread_mutex_unlock(&async.writerMutex);
01228     sched_yield();
01229   }
01230   if( cnt>=0 ){
01231     TRACE(("WAIT\n"));
01232     pthread_mutex_lock(&async.queueMutex);
01233     pthread_cond_broadcast(&async.queueSignal);
01234     pthread_mutex_unlock(&async.queueMutex);
01235     pthread_mutex_lock(&async.writerMutex);
01236     pthread_mutex_unlock(&async.writerMutex);
01237   }else{
01238     TRACE(("NO-WAIT\n"));
01239   }
01240   return TCL_OK;
01241 }
01242 
01243 
01244 #endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */
01245 
01246 /*
01247 ** This routine registers the custom TCL commands defined in this
01248 ** module.  This should be the only procedure visible from outside
01249 ** of this module.
01250 */
01251 int Sqlitetestasync_Init(Tcl_Interp *interp){
01252 #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO)
01253   Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0);
01254   Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0);
01255   Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0);
01256   Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);
01257   Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);
01258   Tcl_LinkVar(interp, "sqlite3async_trace",
01259       (char*)&sqlite3async_trace, TCL_LINK_INT);
01260 #endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */
01261   return TCL_OK;
01262 }