os/persistentdata/persistentstorage/sqlite3api/TEST/SRC/test_async.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/SRC/test_async.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1794 @@
     1.4 +/*
     1.5 +** 2005 December 14
     1.6 +**
     1.7 +** The author disclaims copyright to this source code.  In place of
     1.8 +** a legal notice, here is a blessing:
     1.9 +**
    1.10 +**    May you do good and not evil.
    1.11 +**    May you find forgiveness for yourself and forgive others.
    1.12 +**    May you share freely, never taking more than you give.
    1.13 +**
    1.14 +*************************************************************************
    1.15 +**
    1.16 +** $Id: test_async.c,v 1.48 2008/09/26 20:02:50 drh Exp $
    1.17 +**
    1.18 +** This file contains an example implementation of an asynchronous IO 
    1.19 +** backend for SQLite.
    1.20 +**
    1.21 +** WHAT IS ASYNCHRONOUS I/O?
    1.22 +**
    1.23 +** With asynchronous I/O, write requests are handled by a separate thread
    1.24 +** running in the background.  This means that the thread that initiates
    1.25 +** a database write does not have to wait for (sometimes slow) disk I/O
    1.26 +** to occur.  The write seems to happen very quickly, though in reality
    1.27 +** it is happening at its usual slow pace in the background.
    1.28 +**
    1.29 +** Asynchronous I/O appears to give better responsiveness, but at a price.
    1.30 +** You lose the Durable property.  With the default I/O backend of SQLite,
    1.31 +** once a write completes, you know that the information you wrote is
    1.32 +** safely on disk.  With the asynchronous I/O, this is not the case.  If
    1.33 +** your program crashes or if a power loss occurs after the database
    1.34 +** write but before the asynchronous write thread has completed, then the
    1.35 +** database change might never make it to disk and the next user of the
    1.36 +** database might not see your change.
    1.37 +**
    1.38 +** You lose Durability with asynchronous I/O, but you still retain the
    1.39 +** other parts of ACID:  Atomic,  Consistent, and Isolated.  Many
    1.40 +** appliations get along fine without the Durablity.
    1.41 +**
    1.42 +** HOW IT WORKS
    1.43 +**
    1.44 +** Asynchronous I/O works by creating a special SQLite "vfs" structure
    1.45 +** and registering it with sqlite3_vfs_register(). When files opened via 
    1.46 +** this vfs are written to (using sqlite3OsWrite()), the data is not 
    1.47 +** written directly to disk, but is placed in the "write-queue" to be
    1.48 +** handled by the background thread.
    1.49 +**
    1.50 +** When files opened with the asynchronous vfs are read from 
    1.51 +** (using sqlite3OsRead()), the data is read from the file on 
    1.52 +** disk and the write-queue, so that from the point of view of
    1.53 +** the vfs reader the OsWrite() appears to have already completed.
    1.54 +**
    1.55 +** The special vfs is registered (and unregistered) by calls to 
    1.56 +** function asyncEnable() (see below).
    1.57 +**
    1.58 +** LIMITATIONS
    1.59 +**
    1.60 +** This demonstration code is deliberately kept simple in order to keep
    1.61 +** the main ideas clear and easy to understand.  Real applications that
    1.62 +** want to do asynchronous I/O might want to add additional capabilities.
    1.63 +** For example, in this demonstration if writes are happening at a steady
    1.64 +** stream that exceeds the I/O capability of the background writer thread,
    1.65 +** the queue of pending write operations will grow without bound until we
    1.66 +** run out of memory.  Users of this technique may want to keep track of
    1.67 +** the quantity of pending writes and stop accepting new write requests
    1.68 +** when the buffer gets to be too big.
    1.69 +**
    1.70 +** LOCKING + CONCURRENCY
    1.71 +**
    1.72 +** Multiple connections from within a single process that use this
    1.73 +** implementation of asynchronous IO may access a single database
    1.74 +** file concurrently. From the point of view of the user, if all
    1.75 +** connections are from within a single process, there is no difference
    1.76 +** between the concurrency offered by "normal" SQLite and SQLite
    1.77 +** using the asynchronous backend.
    1.78 +**
    1.79 +** If connections from within multiple database files may access the
    1.80 +** database file, the ENABLE_FILE_LOCKING symbol (see below) must be
    1.81 +** defined. If it is not defined, then no locks are established on 
    1.82 +** the database file. In this case, if multiple processes access 
    1.83 +** the database file, corruption will quickly result.
    1.84 +**
    1.85 +** If ENABLE_FILE_LOCKING is defined (the default), then connections 
    1.86 +** from within multiple processes may access a single database file 
    1.87 +** without risking corruption. However concurrency is reduced as
    1.88 +** follows:
    1.89 +**
    1.90 +**   * When a connection using asynchronous IO begins a database
    1.91 +**     transaction, the database is locked immediately. However the
    1.92 +**     lock is not released until after all relevant operations
    1.93 +**     in the write-queue have been flushed to disk. This means
    1.94 +**     (for example) that the database may remain locked for some 
    1.95 +**     time after a "COMMIT" or "ROLLBACK" is issued.
    1.96 +**
    1.97 +**   * If an application using asynchronous IO executes transactions
    1.98 +**     in quick succession, other database users may be effectively
    1.99 +**     locked out of the database. This is because when a BEGIN
   1.100 +**     is executed, a database lock is established immediately. But
   1.101 +**     when the corresponding COMMIT or ROLLBACK occurs, the lock
   1.102 +**     is not released until the relevant part of the write-queue 
   1.103 +**     has been flushed through. As a result, if a COMMIT is followed
   1.104 +**     by a BEGIN before the write-queue is flushed through, the database 
   1.105 +**     is never unlocked,preventing other processes from accessing 
   1.106 +**     the database.
   1.107 +**
   1.108 +** Defining ENABLE_FILE_LOCKING when using an NFS or other remote 
   1.109 +** file-system may slow things down, as synchronous round-trips to the 
   1.110 +** server may be required to establish database file locks.
   1.111 +*/
   1.112 +#define ENABLE_FILE_LOCKING
   1.113 +
   1.114 +#ifndef SQLITE_AMALGAMATION
   1.115 +# include "sqlite3.h"
   1.116 +# include <assert.h>
   1.117 +# include <string.h>
   1.118 +#endif
   1.119 +#include "tcl.h"
   1.120 +
   1.121 +/*
   1.122 +** This test uses pthreads and hence only works on unix and with
   1.123 +** a threadsafe build of SQLite.
   1.124 +*/
   1.125 +#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
   1.126 +
   1.127 +/*
   1.128 +** This demo uses pthreads.  If you do not have a pthreads implementation
   1.129 +** for your operating system, you will need to recode the threading 
   1.130 +** logic.
   1.131 +*/
   1.132 +#include <pthread.h>
   1.133 +#include <sched.h>
   1.134 +
   1.135 +/* Useful macros used in several places */
   1.136 +#define MIN(x,y) ((x)<(y)?(x):(y))
   1.137 +#define MAX(x,y) ((x)>(y)?(x):(y))
   1.138 +
   1.139 +/* Forward references */
   1.140 +typedef struct AsyncWrite AsyncWrite;
   1.141 +typedef struct AsyncFile AsyncFile;
   1.142 +typedef struct AsyncFileData AsyncFileData;
   1.143 +typedef struct AsyncFileLock AsyncFileLock;
   1.144 +typedef struct AsyncLock AsyncLock;
   1.145 +
   1.146 +/* Enable for debugging */
   1.147 +static int sqlite3async_trace = 0;
   1.148 +# define ASYNC_TRACE(X) if( sqlite3async_trace ) asyncTrace X
   1.149 +static void asyncTrace(const char *zFormat, ...){
   1.150 +  char *z;
   1.151 +  va_list ap;
   1.152 +  va_start(ap, zFormat);
   1.153 +  z = sqlite3_vmprintf(zFormat, ap);
   1.154 +  va_end(ap);
   1.155 +  fprintf(stderr, "[%d] %s", (int)pthread_self(), z);
   1.156 +  sqlite3_free(z);
   1.157 +}
   1.158 +
   1.159 +/*
   1.160 +** THREAD SAFETY NOTES
   1.161 +**
   1.162 +** Basic rules:
   1.163 +**
   1.164 +**     * Both read and write access to the global write-op queue must be 
   1.165 +**       protected by the async.queueMutex. As are the async.ioError and
   1.166 +**       async.nFile variables.
   1.167 +**
   1.168 +**     * The async.pLock list and all AsyncLock and AsyncFileLock
   1.169 +**       structures must be protected by the async.lockMutex mutex.
   1.170 +**
   1.171 +**     * The file handles from the underlying system are not assumed to 
   1.172 +**       be thread safe.
   1.173 +**
   1.174 +**     * See the last two paragraphs under "The Writer Thread" for
   1.175 +**       an assumption to do with file-handle synchronization by the Os.
   1.176 +**
   1.177 +** Deadlock prevention:
   1.178 +**
   1.179 +**     There are three mutex used by the system: the "writer" mutex, 
   1.180 +**     the "queue" mutex and the "lock" mutex. Rules are:
   1.181 +**
   1.182 +**     * It is illegal to block on the writer mutex when any other mutex
   1.183 +**       are held, and 
   1.184 +**
   1.185 +**     * It is illegal to block on the queue mutex when the lock mutex
   1.186 +**       is held.
   1.187 +**
   1.188 +**     i.e. mutex's must be grabbed in the order "writer", "queue", "lock".
   1.189 +**
   1.190 +** File system operations (invoked by SQLite thread):
   1.191 +**
   1.192 +**     xOpen
   1.193 +**     xDelete
   1.194 +**     xFileExists
   1.195 +**
   1.196 +** File handle operations (invoked by SQLite thread):
   1.197 +**
   1.198 +**         asyncWrite, asyncClose, asyncTruncate, asyncSync 
   1.199 +**    
   1.200 +**     The operations above add an entry to the global write-op list. They
   1.201 +**     prepare the entry, acquire the async.queueMutex momentarily while
   1.202 +**     list pointers are  manipulated to insert the new entry, then release
   1.203 +**     the mutex and signal the writer thread to wake up in case it happens
   1.204 +**     to be asleep.
   1.205 +**
   1.206 +**    
   1.207 +**         asyncRead, asyncFileSize.
   1.208 +**
   1.209 +**     Read operations. Both of these read from both the underlying file
   1.210 +**     first then adjust their result based on pending writes in the 
   1.211 +**     write-op queue.   So async.queueMutex is held for the duration
   1.212 +**     of these operations to prevent other threads from changing the
   1.213 +**     queue in mid operation.
   1.214 +**    
   1.215 +**
   1.216 +**         asyncLock, asyncUnlock, asyncCheckReservedLock
   1.217 +**    
   1.218 +**     These primitives implement in-process locking using a hash table
   1.219 +**     on the file name.  Files are locked correctly for connections coming
   1.220 +**     from the same process.  But other processes cannot see these locks
   1.221 +**     and will therefore not honor them.
   1.222 +**
   1.223 +**
   1.224 +** The writer thread:
   1.225 +**
   1.226 +**     The async.writerMutex is used to make sure only there is only
   1.227 +**     a single writer thread running at a time.
   1.228 +**
   1.229 +**     Inside the writer thread is a loop that works like this:
   1.230 +**
   1.231 +**         WHILE (write-op list is not empty)
   1.232 +**             Do IO operation at head of write-op list
   1.233 +**             Remove entry from head of write-op list
   1.234 +**         END WHILE
   1.235 +**
   1.236 +**     The async.queueMutex is always held during the <write-op list is 
   1.237 +**     not empty> test, and when the entry is removed from the head
   1.238 +**     of the write-op list. Sometimes it is held for the interim
   1.239 +**     period (while the IO is performed), and sometimes it is
   1.240 +**     relinquished. It is relinquished if (a) the IO op is an
   1.241 +**     ASYNC_CLOSE or (b) when the file handle was opened, two of
   1.242 +**     the underlying systems handles were opened on the same
   1.243 +**     file-system entry.
   1.244 +**
   1.245 +**     If condition (b) above is true, then one file-handle 
   1.246 +**     (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the
   1.247 +**     file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush() 
   1.248 +**     threads to perform write() operations. This means that read 
   1.249 +**     operations are not blocked by asynchronous writes (although 
   1.250 +**     asynchronous writes may still be blocked by reads).
   1.251 +**
   1.252 +**     This assumes that the OS keeps two handles open on the same file
   1.253 +**     properly in sync. That is, any read operation that starts after a
   1.254 +**     write operation on the same file system entry has completed returns
   1.255 +**     data consistent with the write. We also assume that if one thread 
   1.256 +**     reads a file while another is writing it all bytes other than the
   1.257 +**     ones actually being written contain valid data.
   1.258 +**
   1.259 +**     If the above assumptions are not true, set the preprocessor symbol
   1.260 +**     SQLITE_ASYNC_TWO_FILEHANDLES to 0.
   1.261 +*/
   1.262 +
   1.263 +#ifndef SQLITE_ASYNC_TWO_FILEHANDLES
   1.264 +/* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */
   1.265 +#define SQLITE_ASYNC_TWO_FILEHANDLES 1
   1.266 +#endif
   1.267 +
   1.268 +/*
   1.269 +** State information is held in the static variable "async" defined
   1.270 +** as the following structure.
   1.271 +**
   1.272 +** Both async.ioError and async.nFile are protected by async.queueMutex.
   1.273 +*/
   1.274 +static struct TestAsyncStaticData {
   1.275 +  pthread_mutex_t lockMutex;   /* For access to aLock hash table */
   1.276 +  pthread_mutex_t queueMutex;  /* Mutex for access to write operation queue */
   1.277 +  pthread_mutex_t writerMutex; /* Prevents multiple writer threads */
   1.278 +  pthread_cond_t queueSignal;  /* For waking up sleeping writer thread */
   1.279 +  pthread_cond_t emptySignal;  /* Notify when the write queue is empty */
   1.280 +  AsyncWrite *pQueueFirst;     /* Next write operation to be processed */
   1.281 +  AsyncWrite *pQueueLast;      /* Last write operation on the list */
   1.282 +  AsyncLock *pLock;            /* Linked list of all AsyncLock structures */
   1.283 +  volatile int ioDelay;             /* Extra delay between write operations */
   1.284 +  volatile int writerHaltWhenIdle;  /* Writer thread halts when queue empty */
   1.285 +  volatile int writerHaltNow;       /* Writer thread halts after next op */
   1.286 +  int ioError;                 /* True if an IO error has occured */
   1.287 +  int nFile;                   /* Number of open files (from sqlite pov) */
   1.288 +} async = {
   1.289 +  PTHREAD_MUTEX_INITIALIZER,
   1.290 +  PTHREAD_MUTEX_INITIALIZER,
   1.291 +  PTHREAD_MUTEX_INITIALIZER,
   1.292 +  PTHREAD_COND_INITIALIZER,
   1.293 +  PTHREAD_COND_INITIALIZER,
   1.294 +};
   1.295 +
   1.296 +/* Possible values of AsyncWrite.op */
   1.297 +#define ASYNC_NOOP          0
   1.298 +#define ASYNC_WRITE         1
   1.299 +#define ASYNC_SYNC          2
   1.300 +#define ASYNC_TRUNCATE      3
   1.301 +#define ASYNC_CLOSE         4
   1.302 +#define ASYNC_DELETE        5
   1.303 +#define ASYNC_OPENEXCLUSIVE 6
   1.304 +#define ASYNC_UNLOCK        7
   1.305 +
   1.306 +/* Names of opcodes.  Used for debugging only.
   1.307 +** Make sure these stay in sync with the macros above!
   1.308 +*/
   1.309 +static const char *azOpcodeName[] = {
   1.310 +  "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE", "DELETE", "OPENEX", "UNLOCK"
   1.311 +};
   1.312 +
   1.313 +/*
   1.314 +** Entries on the write-op queue are instances of the AsyncWrite
   1.315 +** structure, defined here.
   1.316 +**
   1.317 +** The interpretation of the iOffset and nByte variables varies depending 
   1.318 +** on the value of AsyncWrite.op:
   1.319 +**
   1.320 +** ASYNC_NOOP:
   1.321 +**     No values used.
   1.322 +**
   1.323 +** ASYNC_WRITE:
   1.324 +**     iOffset -> Offset in file to write to.
   1.325 +**     nByte   -> Number of bytes of data to write (pointed to by zBuf).
   1.326 +**
   1.327 +** ASYNC_SYNC:
   1.328 +**     nByte   -> flags to pass to sqlite3OsSync().
   1.329 +**
   1.330 +** ASYNC_TRUNCATE:
   1.331 +**     iOffset -> Size to truncate file to.
   1.332 +**     nByte   -> Unused.
   1.333 +**
   1.334 +** ASYNC_CLOSE:
   1.335 +**     iOffset -> Unused.
   1.336 +**     nByte   -> Unused.
   1.337 +**
   1.338 +** ASYNC_DELETE:
   1.339 +**     iOffset -> Contains the "syncDir" flag.
   1.340 +**     nByte   -> Number of bytes of zBuf points to (file name).
   1.341 +**
   1.342 +** ASYNC_OPENEXCLUSIVE:
   1.343 +**     iOffset -> Value of "delflag".
   1.344 +**     nByte   -> Number of bytes of zBuf points to (file name).
   1.345 +**
   1.346 +** ASYNC_UNLOCK:
   1.347 +**     nByte   -> Argument to sqlite3OsUnlock().
   1.348 +**
   1.349 +**
   1.350 +** For an ASYNC_WRITE operation, zBuf points to the data to write to the file. 
   1.351 +** This space is sqlite3_malloc()d along with the AsyncWrite structure in a
   1.352 +** single blob, so is deleted when sqlite3_free() is called on the parent 
   1.353 +** structure.
   1.354 +*/
   1.355 +struct AsyncWrite {
   1.356 +  AsyncFileData *pFileData;    /* File to write data to or sync */
   1.357 +  int op;                      /* One of ASYNC_xxx etc. */
   1.358 +  sqlite_int64 iOffset;        /* See above */
   1.359 +  int nByte;          /* See above */
   1.360 +  char *zBuf;         /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
   1.361 +  AsyncWrite *pNext;  /* Next write operation (to any file) */
   1.362 +};
   1.363 +
   1.364 +/*
   1.365 +** An instance of this structure is created for each distinct open file 
   1.366 +** (i.e. if two handles are opened on the one file, only one of these
   1.367 +** structures is allocated) and stored in the async.aLock hash table. The
   1.368 +** keys for async.aLock are the full pathnames of the opened files.
   1.369 +**
   1.370 +** AsyncLock.pList points to the head of a linked list of AsyncFileLock
   1.371 +** structures, one for each handle currently open on the file.
   1.372 +**
   1.373 +** If the opened file is not a main-database (the SQLITE_OPEN_MAIN_DB is
   1.374 +** not passed to the sqlite3OsOpen() call), or if ENABLE_FILE_LOCKING is 
   1.375 +** not defined at compile time, variables AsyncLock.pFile and 
   1.376 +** AsyncLock.eLock are never used. Otherwise, pFile is a file handle
   1.377 +** opened on the file in question and used to obtain the file-system 
   1.378 +** locks required by database connections within this process.
   1.379 +**
   1.380 +** See comments above the asyncLock() function for more details on 
   1.381 +** the implementation of database locking used by this backend.
   1.382 +*/
   1.383 +struct AsyncLock {
   1.384 +  char *zFile;
   1.385 +  int nFile;
   1.386 +  sqlite3_file *pFile;
   1.387 +  int eLock;
   1.388 +  AsyncFileLock *pList;
   1.389 +  AsyncLock *pNext;           /* Next in linked list headed by async.pLock */
   1.390 +};
   1.391 +
   1.392 +/*
   1.393 +** An instance of the following structure is allocated along with each
   1.394 +** AsyncFileData structure (see AsyncFileData.lock), but is only used if the
   1.395 +** file was opened with the SQLITE_OPEN_MAIN_DB.
   1.396 +*/
   1.397 +struct AsyncFileLock {
   1.398 +  int eLock;                /* Internally visible lock state (sqlite pov) */
   1.399 +  int eAsyncLock;           /* Lock-state with write-queue unlock */
   1.400 +  AsyncFileLock *pNext;
   1.401 +};
   1.402 +
   1.403 +/* 
   1.404 +** The AsyncFile structure is a subclass of sqlite3_file used for 
   1.405 +** asynchronous IO. 
   1.406 +**
   1.407 +** All of the actual data for the structure is stored in the structure
   1.408 +** pointed to by AsyncFile.pData, which is allocated as part of the
   1.409 +** sqlite3OsOpen() using sqlite3_malloc(). The reason for this is that the
   1.410 +** lifetime of the AsyncFile structure is ended by the caller after OsClose()
   1.411 +** is called, but the data in AsyncFileData may be required by the
   1.412 +** writer thread after that point.
   1.413 +*/
   1.414 +struct AsyncFile {
   1.415 +  sqlite3_io_methods *pMethod;
   1.416 +  AsyncFileData *pData;
   1.417 +};
   1.418 +struct AsyncFileData {
   1.419 +  char *zName;               /* Underlying OS filename - used for debugging */
   1.420 +  int nName;                 /* Number of characters in zName */
   1.421 +  sqlite3_file *pBaseRead;   /* Read handle to the underlying Os file */
   1.422 +  sqlite3_file *pBaseWrite;  /* Write handle to the underlying Os file */
   1.423 +  AsyncFileLock lock;        /* Lock state for this handle */
   1.424 +  AsyncLock *pLock;          /* AsyncLock object for this file system entry */
   1.425 +  AsyncWrite close;
   1.426 +};
   1.427 +
   1.428 +/*
   1.429 +** The following async_XXX functions are debugging wrappers around the
   1.430 +** corresponding pthread_XXX functions:
   1.431 +**
   1.432 +**     pthread_mutex_lock();
   1.433 +**     pthread_mutex_unlock();
   1.434 +**     pthread_mutex_trylock();
   1.435 +**     pthread_cond_wait();
   1.436 +**
   1.437 +** It is illegal to pass any mutex other than those stored in the
   1.438 +** following global variables of these functions.
   1.439 +**
   1.440 +**     async.queueMutex
   1.441 +**     async.writerMutex
   1.442 +**     async.lockMutex
   1.443 +**
   1.444 +** If NDEBUG is defined, these wrappers do nothing except call the 
   1.445 +** corresponding pthreads function. If NDEBUG is not defined, then the
   1.446 +** following variables are used to store the thread-id (as returned
   1.447 +** by pthread_self()) currently holding the mutex, or 0 otherwise:
   1.448 +**
   1.449 +**     asyncdebug.queueMutexHolder
   1.450 +**     asyncdebug.writerMutexHolder
   1.451 +**     asyncdebug.lockMutexHolder
   1.452 +**
   1.453 +** These variables are used by some assert() statements that verify
   1.454 +** the statements made in the "Deadlock Prevention" notes earlier
   1.455 +** in this file.
   1.456 +*/
   1.457 +#ifndef NDEBUG
   1.458 +
   1.459 +static struct TestAsyncDebugData {
   1.460 +  pthread_t lockMutexHolder;
   1.461 +  pthread_t queueMutexHolder;
   1.462 +  pthread_t writerMutexHolder;
   1.463 +} asyncdebug = {0, 0, 0};
   1.464 +
   1.465 +/*
   1.466 +** Wrapper around pthread_mutex_lock(). Checks that we have not violated
   1.467 +** the anti-deadlock rules (see "Deadlock prevention" above).
   1.468 +*/
   1.469 +static int async_mutex_lock(pthread_mutex_t *pMutex){
   1.470 +  int iIdx;
   1.471 +  int rc;
   1.472 +  pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async);
   1.473 +  pthread_t *aHolder = (pthread_t *)(&asyncdebug);
   1.474 +
   1.475 +  /* The code in this 'ifndef NDEBUG' block depends on a certain alignment
   1.476 +   * of the variables in TestAsyncStaticData and TestAsyncDebugData. The
   1.477 +   * following assert() statements check that this has not been changed.
   1.478 +   *
   1.479 +   * Really, these only need to be run once at startup time.
   1.480 +   */
   1.481 +  assert(&(aMutex[0])==&async.lockMutex);
   1.482 +  assert(&(aMutex[1])==&async.queueMutex);
   1.483 +  assert(&(aMutex[2])==&async.writerMutex);
   1.484 +  assert(&(aHolder[0])==&asyncdebug.lockMutexHolder);
   1.485 +  assert(&(aHolder[1])==&asyncdebug.queueMutexHolder);
   1.486 +  assert(&(aHolder[2])==&asyncdebug.writerMutexHolder);
   1.487 +
   1.488 +  assert( pthread_self()!=0 );
   1.489 +
   1.490 +  for(iIdx=0; iIdx<3; iIdx++){
   1.491 +    if( pMutex==&aMutex[iIdx] ) break;
   1.492 +
   1.493 +    /* This is the key assert(). Here we are checking that if the caller
   1.494 +     * is trying to block on async.writerMutex, neither of the other two
   1.495 +     * mutex are held. If the caller is trying to block on async.queueMutex,
   1.496 +     * lockMutex is not held.
   1.497 +     */
   1.498 +    assert(!pthread_equal(aHolder[iIdx], pthread_self()));
   1.499 +  }
   1.500 +  assert(iIdx<3);
   1.501 +
   1.502 +  rc = pthread_mutex_lock(pMutex);
   1.503 +  if( rc==0 ){
   1.504 +    assert(aHolder[iIdx]==0);
   1.505 +    aHolder[iIdx] = pthread_self();
   1.506 +  }
   1.507 +  return rc;
   1.508 +}
   1.509 +
   1.510 +/*
   1.511 +** Wrapper around pthread_mutex_unlock().
   1.512 +*/
   1.513 +static int async_mutex_unlock(pthread_mutex_t *pMutex){
   1.514 +  int iIdx;
   1.515 +  int rc;
   1.516 +  pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async);
   1.517 +  pthread_t *aHolder = (pthread_t *)(&asyncdebug);
   1.518 +
   1.519 +  for(iIdx=0; iIdx<3; iIdx++){
   1.520 +    if( pMutex==&aMutex[iIdx] ) break;
   1.521 +  }
   1.522 +  assert(iIdx<3);
   1.523 +
   1.524 +  assert(pthread_equal(aHolder[iIdx], pthread_self()));
   1.525 +  aHolder[iIdx] = 0;
   1.526 +  rc = pthread_mutex_unlock(pMutex);
   1.527 +  assert(rc==0);
   1.528 +
   1.529 +  return 0;
   1.530 +}
   1.531 +
   1.532 +/*
   1.533 +** Wrapper around pthread_mutex_trylock().
   1.534 +*/
   1.535 +static int async_mutex_trylock(pthread_mutex_t *pMutex){
   1.536 +  int iIdx;
   1.537 +  int rc;
   1.538 +  pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async);
   1.539 +  pthread_t *aHolder = (pthread_t *)(&asyncdebug);
   1.540 +
   1.541 +  for(iIdx=0; iIdx<3; iIdx++){
   1.542 +    if( pMutex==&aMutex[iIdx] ) break;
   1.543 +  }
   1.544 +  assert(iIdx<3);
   1.545 +
   1.546 +  rc = pthread_mutex_trylock(pMutex);
   1.547 +  if( rc==0 ){
   1.548 +    assert(aHolder[iIdx]==0);
   1.549 +    aHolder[iIdx] = pthread_self();
   1.550 +  }
   1.551 +  return rc;
   1.552 +}
   1.553 +
   1.554 +/*
   1.555 +** Wrapper around pthread_cond_wait().
   1.556 +*/
   1.557 +static int async_cond_wait(pthread_cond_t *pCond, pthread_mutex_t *pMutex){
   1.558 +  int iIdx;
   1.559 +  int rc;
   1.560 +  pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async);
   1.561 +  pthread_t *aHolder = (pthread_t *)(&asyncdebug);
   1.562 +
   1.563 +  for(iIdx=0; iIdx<3; iIdx++){
   1.564 +    if( pMutex==&aMutex[iIdx] ) break;
   1.565 +  }
   1.566 +  assert(iIdx<3);
   1.567 +
   1.568 +  assert(pthread_equal(aHolder[iIdx],pthread_self()));
   1.569 +  aHolder[iIdx] = 0;
   1.570 +  rc = pthread_cond_wait(pCond, pMutex);
   1.571 +  if( rc==0 ){
   1.572 +    aHolder[iIdx] = pthread_self();
   1.573 +  }
   1.574 +  return rc;
   1.575 +}
   1.576 +
   1.577 +/*
   1.578 +** Assert that the mutex is held by the current thread.
   1.579 +*/
   1.580 +static void assert_mutex_is_held(pthread_mutex_t *pMutex){
   1.581 +  int iIdx;
   1.582 +  pthread_mutex_t *aMutex = (pthread_mutex_t *)(&async);
   1.583 +  pthread_t *aHolder = (pthread_t *)(&asyncdebug);
   1.584 +
   1.585 +  for(iIdx=0; iIdx<3; iIdx++){
   1.586 +    if( pMutex==&aMutex[iIdx] ) break;
   1.587 +  }
   1.588 +  assert(iIdx<3);
   1.589 +  assert( aHolder[iIdx]==pthread_self() );
   1.590 +}
   1.591 +
   1.592 +/* Call our async_XX wrappers instead of selected pthread_XX functions */
   1.593 +#define pthread_mutex_lock    async_mutex_lock
   1.594 +#define pthread_mutex_unlock  async_mutex_unlock
   1.595 +#define pthread_mutex_trylock async_mutex_trylock
   1.596 +#define pthread_cond_wait     async_cond_wait
   1.597 +
   1.598 +#else    /* if defined(NDEBUG) */
   1.599 +
   1.600 +#define assert_mutex_is_held(X)    /* A no-op when not debugging */
   1.601 +
   1.602 +#endif   /* !defined(NDEBUG) */
   1.603 +
   1.604 +/*
   1.605 +** Add an entry to the end of the global write-op list. pWrite should point 
   1.606 +** to an AsyncWrite structure allocated using sqlite3_malloc().  The writer
   1.607 +** thread will call sqlite3_free() to free the structure after the specified
   1.608 +** operation has been completed.
   1.609 +**
   1.610 +** Once an AsyncWrite structure has been added to the list, it becomes the
   1.611 +** property of the writer thread and must not be read or modified by the
   1.612 +** caller.  
   1.613 +*/
   1.614 +static void addAsyncWrite(AsyncWrite *pWrite){
   1.615 +  /* We must hold the queue mutex in order to modify the queue pointers */
   1.616 +  pthread_mutex_lock(&async.queueMutex);
   1.617 +
   1.618 +  /* Add the record to the end of the write-op queue */
   1.619 +  assert( !pWrite->pNext );
   1.620 +  if( async.pQueueLast ){
   1.621 +    assert( async.pQueueFirst );
   1.622 +    async.pQueueLast->pNext = pWrite;
   1.623 +  }else{
   1.624 +    async.pQueueFirst = pWrite;
   1.625 +  }
   1.626 +  async.pQueueLast = pWrite;
   1.627 +  ASYNC_TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op],
   1.628 +         pWrite->pFileData ? pWrite->pFileData->zName : "-", pWrite->iOffset));
   1.629 +
   1.630 +  if( pWrite->op==ASYNC_CLOSE ){
   1.631 +    async.nFile--;
   1.632 +  }
   1.633 +
   1.634 +  /* Drop the queue mutex */
   1.635 +  pthread_mutex_unlock(&async.queueMutex);
   1.636 +
   1.637 +  /* The writer thread might have been idle because there was nothing
   1.638 +  ** on the write-op queue for it to do.  So wake it up. */
   1.639 +  pthread_cond_signal(&async.queueSignal);
   1.640 +}
   1.641 +
   1.642 +/*
   1.643 +** Increment async.nFile in a thread-safe manner.
   1.644 +*/
   1.645 +static void incrOpenFileCount(){
   1.646 +  /* We must hold the queue mutex in order to modify async.nFile */
   1.647 +  pthread_mutex_lock(&async.queueMutex);
   1.648 +  if( async.nFile==0 ){
   1.649 +    async.ioError = SQLITE_OK;
   1.650 +  }
   1.651 +  async.nFile++;
   1.652 +  pthread_mutex_unlock(&async.queueMutex);
   1.653 +}
   1.654 +
   1.655 +/*
   1.656 +** This is a utility function to allocate and populate a new AsyncWrite
   1.657 +** structure and insert it (via addAsyncWrite() ) into the global list.
   1.658 +*/
   1.659 +static int addNewAsyncWrite(
   1.660 +  AsyncFileData *pFileData, 
   1.661 +  int op, 
   1.662 +  sqlite3_int64 iOffset, 
   1.663 +  int nByte,
   1.664 +  const char *zByte
   1.665 +){
   1.666 +  AsyncWrite *p;
   1.667 +  if( op!=ASYNC_CLOSE && async.ioError ){
   1.668 +    return async.ioError;
   1.669 +  }
   1.670 +  p = sqlite3_malloc(sizeof(AsyncWrite) + (zByte?nByte:0));
   1.671 +  if( !p ){
   1.672 +    /* The upper layer does not expect operations like OsWrite() to
   1.673 +    ** return SQLITE_NOMEM. This is partly because under normal conditions
   1.674 +    ** SQLite is required to do rollback without calling malloc(). So
   1.675 +    ** if malloc() fails here, treat it as an I/O error. The above
   1.676 +    ** layer knows how to handle that.
   1.677 +    */
   1.678 +    return SQLITE_IOERR;
   1.679 +  }
   1.680 +  p->op = op;
   1.681 +  p->iOffset = iOffset;
   1.682 +  p->nByte = nByte;
   1.683 +  p->pFileData = pFileData;
   1.684 +  p->pNext = 0;
   1.685 +  if( zByte ){
   1.686 +    p->zBuf = (char *)&p[1];
   1.687 +    memcpy(p->zBuf, zByte, nByte);
   1.688 +  }else{
   1.689 +    p->zBuf = 0;
   1.690 +  }
   1.691 +  addAsyncWrite(p);
   1.692 +  return SQLITE_OK;
   1.693 +}
   1.694 +
   1.695 +/*
   1.696 +** Close the file. This just adds an entry to the write-op list, the file is
   1.697 +** not actually closed.
   1.698 +*/
   1.699 +static int asyncClose(sqlite3_file *pFile){
   1.700 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.701 +
   1.702 +  /* Unlock the file, if it is locked */
   1.703 +  pthread_mutex_lock(&async.lockMutex);
   1.704 +  p->lock.eLock = 0;
   1.705 +  pthread_mutex_unlock(&async.lockMutex);
   1.706 +
   1.707 +  addAsyncWrite(&p->close);
   1.708 +  return SQLITE_OK;
   1.709 +}
   1.710 +
   1.711 +/*
   1.712 +** Implementation of sqlite3OsWrite() for asynchronous files. Instead of 
   1.713 +** writing to the underlying file, this function adds an entry to the end of
   1.714 +** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
   1.715 +** returned.
   1.716 +*/
   1.717 +static int asyncWrite(
   1.718 +  sqlite3_file *pFile, 
   1.719 +  const void *pBuf, 
   1.720 +  int amt, 
   1.721 +  sqlite3_int64 iOff
   1.722 +){
   1.723 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.724 +  return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf);
   1.725 +}
   1.726 +
   1.727 +/*
   1.728 +** Read data from the file. First we read from the filesystem, then adjust 
   1.729 +** the contents of the buffer based on ASYNC_WRITE operations in the 
   1.730 +** write-op queue.
   1.731 +**
   1.732 +** This method holds the mutex from start to finish.
   1.733 +*/
   1.734 +static int asyncRead(
   1.735 +  sqlite3_file *pFile, 
   1.736 +  void *zOut, 
   1.737 +  int iAmt, 
   1.738 +  sqlite3_int64 iOffset
   1.739 +){
   1.740 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.741 +  int rc = SQLITE_OK;
   1.742 +  sqlite3_int64 filesize;
   1.743 +  int nRead;
   1.744 +  sqlite3_file *pBase = p->pBaseRead;
   1.745 +
   1.746 +  /* Grab the write queue mutex for the duration of the call */
   1.747 +  pthread_mutex_lock(&async.queueMutex);
   1.748 +
   1.749 +  /* If an I/O error has previously occurred in this virtual file 
   1.750 +  ** system, then all subsequent operations fail.
   1.751 +  */
   1.752 +  if( async.ioError!=SQLITE_OK ){
   1.753 +    rc = async.ioError;
   1.754 +    goto asyncread_out;
   1.755 +  }
   1.756 +
   1.757 +  if( pBase->pMethods ){
   1.758 +    rc = pBase->pMethods->xFileSize(pBase, &filesize);
   1.759 +    if( rc!=SQLITE_OK ){
   1.760 +      goto asyncread_out;
   1.761 +    }
   1.762 +    nRead = MIN(filesize - iOffset, iAmt);
   1.763 +    if( nRead>0 ){
   1.764 +      rc = pBase->pMethods->xRead(pBase, zOut, nRead, iOffset);
   1.765 +      ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset));
   1.766 +    }
   1.767 +  }
   1.768 +
   1.769 +  if( rc==SQLITE_OK ){
   1.770 +    AsyncWrite *pWrite;
   1.771 +    char *zName = p->zName;
   1.772 +
   1.773 +    for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
   1.774 +      if( pWrite->op==ASYNC_WRITE && (
   1.775 +        (pWrite->pFileData==p) ||
   1.776 +        (zName && pWrite->pFileData->zName==zName)
   1.777 +      )){
   1.778 +        int iBeginOut = (pWrite->iOffset-iOffset);
   1.779 +        int iBeginIn = -iBeginOut;
   1.780 +        int nCopy;
   1.781 +
   1.782 +        if( iBeginIn<0 ) iBeginIn = 0;
   1.783 +        if( iBeginOut<0 ) iBeginOut = 0;
   1.784 +        nCopy = MIN(pWrite->nByte-iBeginIn, iAmt-iBeginOut);
   1.785 +
   1.786 +        if( nCopy>0 ){
   1.787 +          memcpy(&((char *)zOut)[iBeginOut], &pWrite->zBuf[iBeginIn], nCopy);
   1.788 +          ASYNC_TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset));
   1.789 +        }
   1.790 +      }
   1.791 +    }
   1.792 +  }
   1.793 +
   1.794 +asyncread_out:
   1.795 +  pthread_mutex_unlock(&async.queueMutex);
   1.796 +  return rc;
   1.797 +}
   1.798 +
   1.799 +/*
   1.800 +** Truncate the file to nByte bytes in length. This just adds an entry to 
   1.801 +** the write-op list, no IO actually takes place.
   1.802 +*/
   1.803 +static int asyncTruncate(sqlite3_file *pFile, sqlite3_int64 nByte){
   1.804 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.805 +  return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0);
   1.806 +}
   1.807 +
   1.808 +/*
   1.809 +** Sync the file. This just adds an entry to the write-op list, the 
   1.810 +** sync() is done later by sqlite3_async_flush().
   1.811 +*/
   1.812 +static int asyncSync(sqlite3_file *pFile, int flags){
   1.813 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.814 +  return addNewAsyncWrite(p, ASYNC_SYNC, 0, flags, 0);
   1.815 +}
   1.816 +
   1.817 +/*
   1.818 +** Read the size of the file. First we read the size of the file system 
   1.819 +** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations 
   1.820 +** currently in the write-op list. 
   1.821 +**
   1.822 +** This method holds the mutex from start to finish.
   1.823 +*/
   1.824 +int asyncFileSize(sqlite3_file *pFile, sqlite3_int64 *piSize){
   1.825 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.826 +  int rc = SQLITE_OK;
   1.827 +  sqlite3_int64 s = 0;
   1.828 +  sqlite3_file *pBase;
   1.829 +
   1.830 +  pthread_mutex_lock(&async.queueMutex);
   1.831 +
   1.832 +  /* Read the filesystem size from the base file. If pBaseRead is NULL, this
   1.833 +  ** means the file hasn't been opened yet. In this case all relevant data 
   1.834 +  ** must be in the write-op queue anyway, so we can omit reading from the
   1.835 +  ** file-system.
   1.836 +  */
   1.837 +  pBase = p->pBaseRead;
   1.838 +  if( pBase->pMethods ){
   1.839 +    rc = pBase->pMethods->xFileSize(pBase, &s);
   1.840 +  }
   1.841 +
   1.842 +  if( rc==SQLITE_OK ){
   1.843 +    AsyncWrite *pWrite;
   1.844 +    for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
   1.845 +      if( pWrite->op==ASYNC_DELETE 
   1.846 +       && p->zName 
   1.847 +       && strcmp(p->zName, pWrite->zBuf)==0 
   1.848 +      ){
   1.849 +        s = 0;
   1.850 +      }else if( pWrite->pFileData && (
   1.851 +          (pWrite->pFileData==p) 
   1.852 +       || (p->zName && pWrite->pFileData->zName==p->zName) 
   1.853 +      )){
   1.854 +        switch( pWrite->op ){
   1.855 +          case ASYNC_WRITE:
   1.856 +            s = MAX(pWrite->iOffset + (sqlite3_int64)(pWrite->nByte), s);
   1.857 +            break;
   1.858 +          case ASYNC_TRUNCATE:
   1.859 +            s = MIN(s, pWrite->iOffset);
   1.860 +            break;
   1.861 +        }
   1.862 +      }
   1.863 +    }
   1.864 +    *piSize = s;
   1.865 +  }
   1.866 +  pthread_mutex_unlock(&async.queueMutex);
   1.867 +  return rc;
   1.868 +}
   1.869 +
   1.870 +/*
   1.871 +** Lock or unlock the actual file-system entry.
   1.872 +*/
   1.873 +static int getFileLock(AsyncLock *pLock){
   1.874 +  int rc = SQLITE_OK;
   1.875 +  AsyncFileLock *pIter;
   1.876 +  int eRequired = 0;
   1.877 +
   1.878 +  if( pLock->pFile ){
   1.879 +    for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
   1.880 +      assert(pIter->eAsyncLock>=pIter->eLock);
   1.881 +      if( pIter->eAsyncLock>eRequired ){
   1.882 +        eRequired = pIter->eAsyncLock;
   1.883 +        assert(eRequired>=0 && eRequired<=SQLITE_LOCK_EXCLUSIVE);
   1.884 +      }
   1.885 +    }
   1.886 +
   1.887 +    if( eRequired>pLock->eLock ){
   1.888 +      rc = pLock->pFile->pMethods->xLock(pLock->pFile, eRequired);
   1.889 +      if( rc==SQLITE_OK ){
   1.890 +        pLock->eLock = eRequired;
   1.891 +      }
   1.892 +    }
   1.893 +    else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){
   1.894 +      rc = pLock->pFile->pMethods->xUnlock(pLock->pFile, eRequired);
   1.895 +      if( rc==SQLITE_OK ){
   1.896 +        pLock->eLock = eRequired;
   1.897 +      }
   1.898 +    }
   1.899 +  }
   1.900 +
   1.901 +  return rc;
   1.902 +}
   1.903 +
   1.904 +/*
   1.905 +** Return the AsyncLock structure from the global async.pLock list 
   1.906 +** associated with the file-system entry identified by path zName 
   1.907 +** (a string of nName bytes). If no such structure exists, return 0.
   1.908 +*/
   1.909 +static AsyncLock *findLock(const char *zName, int nName){
   1.910 +  AsyncLock *p = async.pLock;
   1.911 +  while( p && (p->nFile!=nName || memcmp(p->zFile, zName, nName)) ){
   1.912 +    p = p->pNext;
   1.913 +  }
   1.914 +  return p;
   1.915 +}
   1.916 +
   1.917 +/*
   1.918 +** The following two methods - asyncLock() and asyncUnlock() - are used
   1.919 +** to obtain and release locks on database files opened with the
   1.920 +** asynchronous backend.
   1.921 +*/
   1.922 +static int asyncLock(sqlite3_file *pFile, int eLock){
   1.923 +  int rc = SQLITE_OK;
   1.924 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.925 +
   1.926 +  if( p->zName ){
   1.927 +    pthread_mutex_lock(&async.lockMutex);
   1.928 +    if( p->lock.eLock<eLock ){
   1.929 +      AsyncLock *pLock = p->pLock;
   1.930 +      AsyncFileLock *pIter;
   1.931 +      assert(pLock && pLock->pList);
   1.932 +      for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
   1.933 +        if( pIter!=&p->lock && (
   1.934 +          (eLock==SQLITE_LOCK_EXCLUSIVE && pIter->eLock>=SQLITE_LOCK_SHARED) ||
   1.935 +          (eLock==SQLITE_LOCK_PENDING && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
   1.936 +          (eLock==SQLITE_LOCK_RESERVED && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
   1.937 +          (eLock==SQLITE_LOCK_SHARED && pIter->eLock>=SQLITE_LOCK_PENDING)
   1.938 +        )){
   1.939 +          rc = SQLITE_BUSY;
   1.940 +        }
   1.941 +      }
   1.942 +      if( rc==SQLITE_OK ){
   1.943 +        p->lock.eLock = eLock;
   1.944 +        p->lock.eAsyncLock = MAX(p->lock.eAsyncLock, eLock);
   1.945 +      }
   1.946 +      assert(p->lock.eAsyncLock>=p->lock.eLock);
   1.947 +      if( rc==SQLITE_OK ){
   1.948 +        rc = getFileLock(pLock);
   1.949 +      }
   1.950 +    }
   1.951 +    pthread_mutex_unlock(&async.lockMutex);
   1.952 +  }
   1.953 +
   1.954 +  ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc));
   1.955 +  return rc;
   1.956 +}
   1.957 +static int asyncUnlock(sqlite3_file *pFile, int eLock){
   1.958 +  int rc = SQLITE_OK;
   1.959 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.960 +  if( p->zName ){
   1.961 +    AsyncFileLock *pLock = &p->lock;
   1.962 +    pthread_mutex_lock(&async.lockMutex);
   1.963 +    pLock->eLock = MIN(pLock->eLock, eLock);
   1.964 +    pthread_mutex_unlock(&async.lockMutex);
   1.965 +    rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
   1.966 +  }
   1.967 +  return rc;
   1.968 +}
   1.969 +
   1.970 +/*
   1.971 +** This function is called when the pager layer first opens a database file
   1.972 +** and is checking for a hot-journal.
   1.973 +*/
   1.974 +static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   1.975 +  int ret = 0;
   1.976 +  AsyncFileLock *pIter;
   1.977 +  AsyncFileData *p = ((AsyncFile *)pFile)->pData;
   1.978 +
   1.979 +  pthread_mutex_lock(&async.lockMutex);
   1.980 +  for(pIter=p->pLock->pList; pIter; pIter=pIter->pNext){
   1.981 +    if( pIter->eLock>=SQLITE_LOCK_RESERVED ){
   1.982 +      ret = 1;
   1.983 +    }
   1.984 +  }
   1.985 +  pthread_mutex_unlock(&async.lockMutex);
   1.986 +
   1.987 +  ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", ret, p->zName));
   1.988 +  *pResOut = ret;
   1.989 +  return SQLITE_OK;
   1.990 +}
   1.991 +
   1.992 +/* 
   1.993 +** sqlite3_file_control() implementation.
   1.994 +*/
   1.995 +static int asyncFileControl(sqlite3_file *id, int op, void *pArg){
   1.996 +  switch( op ){
   1.997 +    case SQLITE_FCNTL_LOCKSTATE: {
   1.998 +      pthread_mutex_lock(&async.lockMutex);
   1.999 +      *(int*)pArg = ((AsyncFile*)id)->pData->lock.eLock;
  1.1000 +      pthread_mutex_unlock(&async.lockMutex);
  1.1001 +      return SQLITE_OK;
  1.1002 +    }
  1.1003 +  }
  1.1004 +  return SQLITE_ERROR;
  1.1005 +}
  1.1006 +
  1.1007 +/* 
  1.1008 +** Return the device characteristics and sector-size of the device. It
  1.1009 +** is not tricky to implement these correctly, as this backend might 
  1.1010 +** not have an open file handle at this point.
  1.1011 +*/
  1.1012 +static int asyncSectorSize(sqlite3_file *pFile){
  1.1013 +  return 512;
  1.1014 +}
  1.1015 +static int asyncDeviceCharacteristics(sqlite3_file *pFile){
  1.1016 +  return 0;
  1.1017 +}
  1.1018 +
  1.1019 +static int unlinkAsyncFile(AsyncFileData *pData){
  1.1020 +  AsyncFileLock **ppIter;
  1.1021 +  int rc = SQLITE_OK;
  1.1022 +
  1.1023 +  if( pData->zName ){
  1.1024 +    AsyncLock *pLock = pData->pLock;
  1.1025 +    for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){
  1.1026 +      if( (*ppIter)==&pData->lock ){
  1.1027 +        *ppIter = pData->lock.pNext;
  1.1028 +        break;
  1.1029 +      }
  1.1030 +    }
  1.1031 +    if( !pLock->pList ){
  1.1032 +      AsyncLock **pp;
  1.1033 +      if( pLock->pFile ){
  1.1034 +        pLock->pFile->pMethods->xClose(pLock->pFile);
  1.1035 +      }
  1.1036 +      for(pp=&async.pLock; *pp!=pLock; pp=&((*pp)->pNext));
  1.1037 +      *pp = pLock->pNext;
  1.1038 +      sqlite3_free(pLock);
  1.1039 +    }else{
  1.1040 +      rc = getFileLock(pLock);
  1.1041 +    }
  1.1042 +  }
  1.1043 +
  1.1044 +  return rc;
  1.1045 +}
  1.1046 +
  1.1047 +/*
  1.1048 +** Open a file.
  1.1049 +*/
  1.1050 +static int asyncOpen(
  1.1051 +  sqlite3_vfs *pAsyncVfs,
  1.1052 +  const char *zName,
  1.1053 +  sqlite3_file *pFile,
  1.1054 +  int flags,
  1.1055 +  int *pOutFlags
  1.1056 +){
  1.1057 +  static sqlite3_io_methods async_methods = {
  1.1058 +    1,                               /* iVersion */
  1.1059 +    asyncClose,                      /* xClose */
  1.1060 +    asyncRead,                       /* xRead */
  1.1061 +    asyncWrite,                      /* xWrite */
  1.1062 +    asyncTruncate,                   /* xTruncate */
  1.1063 +    asyncSync,                       /* xSync */
  1.1064 +    asyncFileSize,                   /* xFileSize */
  1.1065 +    asyncLock,                       /* xLock */
  1.1066 +    asyncUnlock,                     /* xUnlock */
  1.1067 +    asyncCheckReservedLock,          /* xCheckReservedLock */
  1.1068 +    asyncFileControl,                /* xFileControl */
  1.1069 +    asyncSectorSize,                 /* xSectorSize */
  1.1070 +    asyncDeviceCharacteristics       /* xDeviceCharacteristics */
  1.1071 +  };
  1.1072 +
  1.1073 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1074 +  AsyncFile *p = (AsyncFile *)pFile;
  1.1075 +  int nName = 0;
  1.1076 +  int rc = SQLITE_OK;
  1.1077 +  int nByte;
  1.1078 +  AsyncFileData *pData;
  1.1079 +  AsyncLock *pLock = 0;
  1.1080 +  char *z;
  1.1081 +  int isExclusive = (flags&SQLITE_OPEN_EXCLUSIVE);
  1.1082 +
  1.1083 +  /* If zName is NULL, then the upper layer is requesting an anonymous file */
  1.1084 +  if( zName ){
  1.1085 +    nName = strlen(zName)+1;
  1.1086 +  }
  1.1087 +
  1.1088 +  nByte = (
  1.1089 +    sizeof(AsyncFileData) +        /* AsyncFileData structure */
  1.1090 +    2 * pVfs->szOsFile +           /* AsyncFileData.pBaseRead and pBaseWrite */
  1.1091 +    nName                          /* AsyncFileData.zName */
  1.1092 +  ); 
  1.1093 +  z = sqlite3_malloc(nByte);
  1.1094 +  if( !z ){
  1.1095 +    return SQLITE_NOMEM;
  1.1096 +  }
  1.1097 +  memset(z, 0, nByte);
  1.1098 +  pData = (AsyncFileData*)z;
  1.1099 +  z += sizeof(pData[0]);
  1.1100 +  pData->pBaseRead = (sqlite3_file*)z;
  1.1101 +  z += pVfs->szOsFile;
  1.1102 +  pData->pBaseWrite = (sqlite3_file*)z;
  1.1103 +  pData->close.pFileData = pData;
  1.1104 +  pData->close.op = ASYNC_CLOSE;
  1.1105 +
  1.1106 +  if( zName ){
  1.1107 +    z += pVfs->szOsFile;
  1.1108 +    pData->zName = z;
  1.1109 +    pData->nName = nName;
  1.1110 +    memcpy(pData->zName, zName, nName);
  1.1111 +  }
  1.1112 +
  1.1113 +  if( !isExclusive ){
  1.1114 +    rc = pVfs->xOpen(pVfs, zName, pData->pBaseRead, flags, pOutFlags);
  1.1115 +    if( rc==SQLITE_OK && ((*pOutFlags)&SQLITE_OPEN_READWRITE) ){
  1.1116 +      rc = pVfs->xOpen(pVfs, zName, pData->pBaseWrite, flags, 0);
  1.1117 +    }
  1.1118 +  }
  1.1119 +
  1.1120 +  pthread_mutex_lock(&async.lockMutex);
  1.1121 +
  1.1122 +  if( zName && rc==SQLITE_OK ){
  1.1123 +    pLock = findLock(pData->zName, pData->nName);
  1.1124 +    if( !pLock ){
  1.1125 +      int nByte = pVfs->szOsFile + sizeof(AsyncLock) + pData->nName + 1; 
  1.1126 +      pLock = (AsyncLock *)sqlite3_malloc(nByte);
  1.1127 +      if( pLock ){
  1.1128 +        memset(pLock, 0, nByte);
  1.1129 +#ifdef ENABLE_FILE_LOCKING
  1.1130 +        if( flags&SQLITE_OPEN_MAIN_DB ){
  1.1131 +          pLock->pFile = (sqlite3_file *)&pLock[1];
  1.1132 +          rc = pVfs->xOpen(pVfs, zName, pLock->pFile, flags, 0);
  1.1133 +          if( rc!=SQLITE_OK ){
  1.1134 +            sqlite3_free(pLock);
  1.1135 +            pLock = 0;
  1.1136 +          }
  1.1137 +        }
  1.1138 +#endif
  1.1139 +        if( pLock ){
  1.1140 +          pLock->nFile = pData->nName;
  1.1141 +          pLock->zFile = &((char *)(&pLock[1]))[pVfs->szOsFile];
  1.1142 +          memcpy(pLock->zFile, pData->zName, pLock->nFile);
  1.1143 +          pLock->pNext = async.pLock;
  1.1144 +          async.pLock = pLock;
  1.1145 +        }
  1.1146 +      }else{
  1.1147 +        rc = SQLITE_NOMEM;
  1.1148 +      }
  1.1149 +    }
  1.1150 +  }
  1.1151 +
  1.1152 +  if( rc==SQLITE_OK ){
  1.1153 +    p->pMethod = &async_methods;
  1.1154 +    p->pData = pData;
  1.1155 +
  1.1156 +    /* Link AsyncFileData.lock into the linked list of 
  1.1157 +    ** AsyncFileLock structures for this file.
  1.1158 +    */
  1.1159 +    if( zName ){
  1.1160 +      pData->lock.pNext = pLock->pList;
  1.1161 +      pLock->pList = &pData->lock;
  1.1162 +      pData->zName = pLock->zFile;
  1.1163 +    }
  1.1164 +  }else{
  1.1165 +    if( pData->pBaseRead->pMethods ){
  1.1166 +      pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
  1.1167 +    }
  1.1168 +    if( pData->pBaseWrite->pMethods ){
  1.1169 +      pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
  1.1170 +    }
  1.1171 +    sqlite3_free(pData);
  1.1172 +  }
  1.1173 +
  1.1174 +  pthread_mutex_unlock(&async.lockMutex);
  1.1175 +
  1.1176 +  if( rc==SQLITE_OK ){
  1.1177 +    incrOpenFileCount();
  1.1178 +    pData->pLock = pLock;
  1.1179 +  }
  1.1180 +
  1.1181 +  if( rc==SQLITE_OK && isExclusive ){
  1.1182 +    rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (sqlite3_int64)flags,0,0);
  1.1183 +    if( rc==SQLITE_OK ){
  1.1184 +      if( pOutFlags ) *pOutFlags = flags;
  1.1185 +    }else{
  1.1186 +      pthread_mutex_lock(&async.lockMutex);
  1.1187 +      unlinkAsyncFile(pData);
  1.1188 +      pthread_mutex_unlock(&async.lockMutex);
  1.1189 +      sqlite3_free(pData);
  1.1190 +    }
  1.1191 +  }
  1.1192 +  return rc;
  1.1193 +}
  1.1194 +
  1.1195 +/*
  1.1196 +** Implementation of sqlite3OsDelete. Add an entry to the end of the 
  1.1197 +** write-op queue to perform the delete.
  1.1198 +*/
  1.1199 +static int asyncDelete(sqlite3_vfs *pAsyncVfs, const char *z, int syncDir){
  1.1200 +  return addNewAsyncWrite(0, ASYNC_DELETE, syncDir, strlen(z)+1, z);
  1.1201 +}
  1.1202 +
  1.1203 +/*
  1.1204 +** Implementation of sqlite3OsAccess. This method holds the mutex from
  1.1205 +** start to finish.
  1.1206 +*/
  1.1207 +static int asyncAccess(
  1.1208 +  sqlite3_vfs *pAsyncVfs, 
  1.1209 +  const char *zName, 
  1.1210 +  int flags,
  1.1211 +  int *pResOut
  1.1212 +){
  1.1213 +  int rc;
  1.1214 +  int ret;
  1.1215 +  AsyncWrite *p;
  1.1216 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1217 +
  1.1218 +  assert(flags==SQLITE_ACCESS_READWRITE 
  1.1219 +      || flags==SQLITE_ACCESS_READ 
  1.1220 +      || flags==SQLITE_ACCESS_EXISTS 
  1.1221 +  );
  1.1222 +
  1.1223 +  pthread_mutex_lock(&async.queueMutex);
  1.1224 +  rc = pVfs->xAccess(pVfs, zName, flags, &ret);
  1.1225 +  if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
  1.1226 +    for(p=async.pQueueFirst; p; p = p->pNext){
  1.1227 +      if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){
  1.1228 +        ret = 0;
  1.1229 +      }else if( p->op==ASYNC_OPENEXCLUSIVE 
  1.1230 +             && p->pFileData->zName
  1.1231 +             && 0==strcmp(p->pFileData->zName, zName) 
  1.1232 +      ){
  1.1233 +        ret = 1;
  1.1234 +      }
  1.1235 +    }
  1.1236 +  }
  1.1237 +  ASYNC_TRACE(("ACCESS(%s): %s = %d\n", 
  1.1238 +    flags==SQLITE_ACCESS_READWRITE?"read-write":
  1.1239 +    flags==SQLITE_ACCESS_READ?"read":"exists"
  1.1240 +    , zName, ret)
  1.1241 +  );
  1.1242 +  pthread_mutex_unlock(&async.queueMutex);
  1.1243 +  *pResOut = ret;
  1.1244 +  return rc;
  1.1245 +}
  1.1246 +
  1.1247 +/*
  1.1248 +** Fill in zPathOut with the full path to the file identified by zPath.
  1.1249 +*/
  1.1250 +static int asyncFullPathname(
  1.1251 +  sqlite3_vfs *pAsyncVfs, 
  1.1252 +  const char *zPath, 
  1.1253 +  int nPathOut,
  1.1254 +  char *zPathOut
  1.1255 +){
  1.1256 +  int rc;
  1.1257 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1258 +  rc = pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
  1.1259 +
  1.1260 +  /* Because of the way intra-process file locking works, this backend
  1.1261 +  ** needs to return a canonical path. The following block assumes the
  1.1262 +  ** file-system uses unix style paths. 
  1.1263 +  */
  1.1264 +  if( rc==SQLITE_OK ){
  1.1265 +    int iIn;
  1.1266 +    int iOut = 0;
  1.1267 +    int nPathOut = strlen(zPathOut);
  1.1268 +
  1.1269 +    for(iIn=0; iIn<nPathOut; iIn++){
  1.1270 +
  1.1271 +      /* Replace any occurences of "//" with "/" */
  1.1272 +      if( iIn<=(nPathOut-2) && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='/'
  1.1273 +      ){
  1.1274 +        continue;
  1.1275 +      }
  1.1276 +
  1.1277 +      /* Replace any occurences of "/./" with "/" */
  1.1278 +      if( iIn<=(nPathOut-3) 
  1.1279 +       && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='.' && zPathOut[iIn+2]=='/'
  1.1280 +      ){
  1.1281 +        iIn++;
  1.1282 +        continue;
  1.1283 +      }
  1.1284 +
  1.1285 +      /* Replace any occurences of "<path-component>/../" with "" */
  1.1286 +      if( iOut>0 && iIn<=(nPathOut-4) 
  1.1287 +       && zPathOut[iIn]=='/' && zPathOut[iIn+1]=='.' 
  1.1288 +       && zPathOut[iIn+2]=='.' && zPathOut[iIn+3]=='/'
  1.1289 +      ){
  1.1290 +        iIn += 3;
  1.1291 +        iOut--;
  1.1292 +        for( ; iOut>0 && zPathOut[iOut-1]!='/'; iOut--);
  1.1293 +        continue;
  1.1294 +      }
  1.1295 +
  1.1296 +      zPathOut[iOut++] = zPathOut[iIn];
  1.1297 +    }
  1.1298 +    zPathOut[iOut] = '\0';
  1.1299 +  }
  1.1300 +
  1.1301 +  return rc;
  1.1302 +}
  1.1303 +static void *asyncDlOpen(sqlite3_vfs *pAsyncVfs, const char *zPath){
  1.1304 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1305 +  return pVfs->xDlOpen(pVfs, zPath);
  1.1306 +}
  1.1307 +static void asyncDlError(sqlite3_vfs *pAsyncVfs, int nByte, char *zErrMsg){
  1.1308 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1309 +  pVfs->xDlError(pVfs, nByte, zErrMsg);
  1.1310 +}
  1.1311 +static void *asyncDlSym(
  1.1312 +  sqlite3_vfs *pAsyncVfs, 
  1.1313 +  void *pHandle, 
  1.1314 +  const char *zSymbol
  1.1315 +){
  1.1316 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1317 +  return pVfs->xDlSym(pVfs, pHandle, zSymbol);
  1.1318 +}
  1.1319 +static void asyncDlClose(sqlite3_vfs *pAsyncVfs, void *pHandle){
  1.1320 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1321 +  pVfs->xDlClose(pVfs, pHandle);
  1.1322 +}
  1.1323 +static int asyncRandomness(sqlite3_vfs *pAsyncVfs, int nByte, char *zBufOut){
  1.1324 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1325 +  return pVfs->xRandomness(pVfs, nByte, zBufOut);
  1.1326 +}
  1.1327 +static int asyncSleep(sqlite3_vfs *pAsyncVfs, int nMicro){
  1.1328 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1329 +  return pVfs->xSleep(pVfs, nMicro);
  1.1330 +}
  1.1331 +static int asyncCurrentTime(sqlite3_vfs *pAsyncVfs, double *pTimeOut){
  1.1332 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
  1.1333 +  return pVfs->xCurrentTime(pVfs, pTimeOut);
  1.1334 +}
  1.1335 +
  1.1336 +static sqlite3_vfs async_vfs = {
  1.1337 +  1,                    /* iVersion */
  1.1338 +  sizeof(AsyncFile),    /* szOsFile */
  1.1339 +  0,                    /* mxPathname */
  1.1340 +  0,                    /* pNext */
  1.1341 +  "async",              /* zName */
  1.1342 +  0,                    /* pAppData */
  1.1343 +  asyncOpen,            /* xOpen */
  1.1344 +  asyncDelete,          /* xDelete */
  1.1345 +  asyncAccess,          /* xAccess */
  1.1346 +  asyncFullPathname,    /* xFullPathname */
  1.1347 +  asyncDlOpen,          /* xDlOpen */
  1.1348 +  asyncDlError,         /* xDlError */
  1.1349 +  asyncDlSym,           /* xDlSym */
  1.1350 +  asyncDlClose,         /* xDlClose */
  1.1351 +  asyncRandomness,      /* xDlError */
  1.1352 +  asyncSleep,           /* xDlSym */
  1.1353 +  asyncCurrentTime      /* xDlClose */
  1.1354 +};
  1.1355 +
  1.1356 +/*
  1.1357 +** Call this routine to enable or disable the
  1.1358 +** asynchronous IO features implemented in this file. 
  1.1359 +**
  1.1360 +** This routine is not even remotely threadsafe.  Do not call
  1.1361 +** this routine while any SQLite database connections are open.
  1.1362 +*/
  1.1363 +static void asyncEnable(int enable){
  1.1364 +  if( enable ){
  1.1365 +    if( !async_vfs.pAppData ){
  1.1366 +      async_vfs.pAppData = (void *)sqlite3_vfs_find(0);
  1.1367 +      async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname;
  1.1368 +      sqlite3_vfs_register(&async_vfs, 1);
  1.1369 +    }
  1.1370 +  }else{
  1.1371 +    if( async_vfs.pAppData ){
  1.1372 +      sqlite3_vfs_unregister(&async_vfs);
  1.1373 +      async_vfs.pAppData = 0;
  1.1374 +    }
  1.1375 +  }
  1.1376 +}
  1.1377 +
  1.1378 +/* 
  1.1379 +** This procedure runs in a separate thread, reading messages off of the
  1.1380 +** write queue and processing them one by one.  
  1.1381 +**
  1.1382 +** If async.writerHaltNow is true, then this procedure exits
  1.1383 +** after processing a single message.
  1.1384 +**
  1.1385 +** If async.writerHaltWhenIdle is true, then this procedure exits when
  1.1386 +** the write queue is empty.
  1.1387 +**
  1.1388 +** If both of the above variables are false, this procedure runs
  1.1389 +** indefinately, waiting for operations to be added to the write queue
  1.1390 +** and processing them in the order in which they arrive.
  1.1391 +**
  1.1392 +** An artifical delay of async.ioDelay milliseconds is inserted before
  1.1393 +** each write operation in order to simulate the effect of a slow disk.
  1.1394 +**
  1.1395 +** Only one instance of this procedure may be running at a time.
  1.1396 +*/
  1.1397 +static void *asyncWriterThread(void *pIsStarted){
  1.1398 +  sqlite3_vfs *pVfs = (sqlite3_vfs *)(async_vfs.pAppData);
  1.1399 +  AsyncWrite *p = 0;
  1.1400 +  int rc = SQLITE_OK;
  1.1401 +  int holdingMutex = 0;
  1.1402 +
  1.1403 +  if( pthread_mutex_trylock(&async.writerMutex) ){
  1.1404 +    return 0;
  1.1405 +  }
  1.1406 +  (*(int *)pIsStarted) = 1;
  1.1407 +  while( async.writerHaltNow==0 ){
  1.1408 +    int doNotFree = 0;
  1.1409 +    sqlite3_file *pBase = 0;
  1.1410 +
  1.1411 +    if( !holdingMutex ){
  1.1412 +      pthread_mutex_lock(&async.queueMutex);
  1.1413 +    }
  1.1414 +    while( (p = async.pQueueFirst)==0 ){
  1.1415 +      pthread_cond_broadcast(&async.emptySignal);
  1.1416 +      if( async.writerHaltWhenIdle ){
  1.1417 +        pthread_mutex_unlock(&async.queueMutex);
  1.1418 +        break;
  1.1419 +      }else{
  1.1420 +        ASYNC_TRACE(("IDLE\n"));
  1.1421 +        pthread_cond_wait(&async.queueSignal, &async.queueMutex);
  1.1422 +        ASYNC_TRACE(("WAKEUP\n"));
  1.1423 +      }
  1.1424 +    }
  1.1425 +    if( p==0 ) break;
  1.1426 +    holdingMutex = 1;
  1.1427 +
  1.1428 +    /* Right now this thread is holding the mutex on the write-op queue.
  1.1429 +    ** Variable 'p' points to the first entry in the write-op queue. In
  1.1430 +    ** the general case, we hold on to the mutex for the entire body of
  1.1431 +    ** the loop. 
  1.1432 +    **
  1.1433 +    ** However in the cases enumerated below, we relinquish the mutex,
  1.1434 +    ** perform the IO, and then re-request the mutex before removing 'p' from
  1.1435 +    ** the head of the write-op queue. The idea is to increase concurrency with
  1.1436 +    ** sqlite threads.
  1.1437 +    **
  1.1438 +    **     * An ASYNC_CLOSE operation.
  1.1439 +    **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish 
  1.1440 +    **       the mutex, call the underlying xOpenExclusive() function, then
  1.1441 +    **       re-aquire the mutex before seting the AsyncFile.pBaseRead 
  1.1442 +    **       variable.
  1.1443 +    **     * ASYNC_SYNC and ASYNC_WRITE operations, if 
  1.1444 +    **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two
  1.1445 +    **       file-handles are open for the particular file being "synced".
  1.1446 +    */
  1.1447 +    if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){
  1.1448 +      p->op = ASYNC_NOOP;
  1.1449 +    }
  1.1450 +    if( p->pFileData ){
  1.1451 +      pBase = p->pFileData->pBaseWrite;
  1.1452 +      if( 
  1.1453 +        p->op==ASYNC_CLOSE || 
  1.1454 +        p->op==ASYNC_OPENEXCLUSIVE ||
  1.1455 +        (pBase->pMethods && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) ) 
  1.1456 +      ){
  1.1457 +        pthread_mutex_unlock(&async.queueMutex);
  1.1458 +        holdingMutex = 0;
  1.1459 +      }
  1.1460 +      if( !pBase->pMethods ){
  1.1461 +        pBase = p->pFileData->pBaseRead;
  1.1462 +      }
  1.1463 +    }
  1.1464 +
  1.1465 +    switch( p->op ){
  1.1466 +      case ASYNC_NOOP:
  1.1467 +        break;
  1.1468 +
  1.1469 +      case ASYNC_WRITE:
  1.1470 +        assert( pBase );
  1.1471 +        ASYNC_TRACE(("WRITE %s %d bytes at %d\n",
  1.1472 +                p->pFileData->zName, p->nByte, p->iOffset));
  1.1473 +        rc = pBase->pMethods->xWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset);
  1.1474 +        break;
  1.1475 +
  1.1476 +      case ASYNC_SYNC:
  1.1477 +        assert( pBase );
  1.1478 +        ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName));
  1.1479 +        rc = pBase->pMethods->xSync(pBase, p->nByte);
  1.1480 +        break;
  1.1481 +
  1.1482 +      case ASYNC_TRUNCATE:
  1.1483 +        assert( pBase );
  1.1484 +        ASYNC_TRACE(("TRUNCATE %s to %d bytes\n", 
  1.1485 +                p->pFileData->zName, p->iOffset));
  1.1486 +        rc = pBase->pMethods->xTruncate(pBase, p->iOffset);
  1.1487 +        break;
  1.1488 +
  1.1489 +      case ASYNC_CLOSE: {
  1.1490 +        AsyncFileData *pData = p->pFileData;
  1.1491 +        ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName));
  1.1492 +        if( pData->pBaseWrite->pMethods ){
  1.1493 +          pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
  1.1494 +        }
  1.1495 +        if( pData->pBaseRead->pMethods ){
  1.1496 +          pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
  1.1497 +        }
  1.1498 +
  1.1499 +        /* Unlink AsyncFileData.lock from the linked list of AsyncFileLock 
  1.1500 +        ** structures for this file. Obtain the async.lockMutex mutex 
  1.1501 +        ** before doing so.
  1.1502 +        */
  1.1503 +        pthread_mutex_lock(&async.lockMutex);
  1.1504 +        rc = unlinkAsyncFile(pData);
  1.1505 +        pthread_mutex_unlock(&async.lockMutex);
  1.1506 +
  1.1507 +        if( !holdingMutex ){
  1.1508 +          pthread_mutex_lock(&async.queueMutex);
  1.1509 +          holdingMutex = 1;
  1.1510 +        }
  1.1511 +        assert_mutex_is_held(&async.queueMutex);
  1.1512 +        async.pQueueFirst = p->pNext;
  1.1513 +        sqlite3_free(pData);
  1.1514 +        doNotFree = 1;
  1.1515 +        break;
  1.1516 +      }
  1.1517 +
  1.1518 +      case ASYNC_UNLOCK: {
  1.1519 +        AsyncFileData *pData = p->pFileData;
  1.1520 +        int eLock = p->nByte;
  1.1521 +        pthread_mutex_lock(&async.lockMutex);
  1.1522 +        pData->lock.eAsyncLock = MIN(
  1.1523 +            pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
  1.1524 +        );
  1.1525 +        assert(pData->lock.eAsyncLock>=pData->lock.eLock);
  1.1526 +        rc = getFileLock(pData->pLock);
  1.1527 +        pthread_mutex_unlock(&async.lockMutex);
  1.1528 +        break;
  1.1529 +      }
  1.1530 +
  1.1531 +      case ASYNC_DELETE:
  1.1532 +        ASYNC_TRACE(("DELETE %s\n", p->zBuf));
  1.1533 +        rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset);
  1.1534 +        break;
  1.1535 +
  1.1536 +      case ASYNC_OPENEXCLUSIVE: {
  1.1537 +        int flags = (int)p->iOffset;
  1.1538 +        AsyncFileData *pData = p->pFileData;
  1.1539 +        ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset));
  1.1540 +        assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0);
  1.1541 +        rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0);
  1.1542 +        assert( holdingMutex==0 );
  1.1543 +        pthread_mutex_lock(&async.queueMutex);
  1.1544 +        holdingMutex = 1;
  1.1545 +        break;
  1.1546 +      }
  1.1547 +
  1.1548 +      default: assert(!"Illegal value for AsyncWrite.op");
  1.1549 +    }
  1.1550 +
  1.1551 +    /* If we didn't hang on to the mutex during the IO op, obtain it now
  1.1552 +    ** so that the AsyncWrite structure can be safely removed from the 
  1.1553 +    ** global write-op queue.
  1.1554 +    */
  1.1555 +    if( !holdingMutex ){
  1.1556 +      pthread_mutex_lock(&async.queueMutex);
  1.1557 +      holdingMutex = 1;
  1.1558 +    }
  1.1559 +    /* ASYNC_TRACE(("UNLINK %p\n", p)); */
  1.1560 +    if( p==async.pQueueLast ){
  1.1561 +      async.pQueueLast = 0;
  1.1562 +    }
  1.1563 +    if( !doNotFree ){
  1.1564 +      assert_mutex_is_held(&async.queueMutex);
  1.1565 +      async.pQueueFirst = p->pNext;
  1.1566 +      sqlite3_free(p);
  1.1567 +    }
  1.1568 +    assert( holdingMutex );
  1.1569 +
  1.1570 +    /* An IO error has occured. We cannot report the error back to the
  1.1571 +    ** connection that requested the I/O since the error happened 
  1.1572 +    ** asynchronously.  The connection has already moved on.  There 
  1.1573 +    ** really is nobody to report the error to.
  1.1574 +    **
  1.1575 +    ** The file for which the error occured may have been a database or
  1.1576 +    ** journal file. Regardless, none of the currently queued operations
  1.1577 +    ** associated with the same database should now be performed. Nor should
  1.1578 +    ** any subsequently requested IO on either a database or journal file 
  1.1579 +    ** handle for the same database be accepted until the main database
  1.1580 +    ** file handle has been closed and reopened.
  1.1581 +    **
  1.1582 +    ** Furthermore, no further IO should be queued or performed on any file
  1.1583 +    ** handle associated with a database that may have been part of a 
  1.1584 +    ** multi-file transaction that included the database associated with 
  1.1585 +    ** the IO error (i.e. a database ATTACHed to the same handle at some 
  1.1586 +    ** point in time).
  1.1587 +    */
  1.1588 +    if( rc!=SQLITE_OK ){
  1.1589 +      async.ioError = rc;
  1.1590 +    }
  1.1591 +
  1.1592 +    if( async.ioError && !async.pQueueFirst ){
  1.1593 +      pthread_mutex_lock(&async.lockMutex);
  1.1594 +      if( 0==async.pLock ){
  1.1595 +        async.ioError = SQLITE_OK;
  1.1596 +      }
  1.1597 +      pthread_mutex_unlock(&async.lockMutex);
  1.1598 +    }
  1.1599 +
  1.1600 +    /* Drop the queue mutex before continuing to the next write operation
  1.1601 +    ** in order to give other threads a chance to work with the write queue.
  1.1602 +    */
  1.1603 +    if( !async.pQueueFirst || !async.ioError ){
  1.1604 +      pthread_mutex_unlock(&async.queueMutex);
  1.1605 +      holdingMutex = 0;
  1.1606 +      if( async.ioDelay>0 ){
  1.1607 +        pVfs->xSleep(pVfs, async.ioDelay);
  1.1608 +      }else{
  1.1609 +        sched_yield();
  1.1610 +      }
  1.1611 +    }
  1.1612 +  }
  1.1613 +  
  1.1614 +  pthread_mutex_unlock(&async.writerMutex);
  1.1615 +  return 0;
  1.1616 +}
  1.1617 +
  1.1618 +/**************************************************************************
  1.1619 +** The remaining code defines a Tcl interface for testing the asynchronous
  1.1620 +** IO implementation in this file.
  1.1621 +**
  1.1622 +** To adapt the code to a non-TCL environment, delete or comment out
  1.1623 +** the code that follows.
  1.1624 +*/
  1.1625 +
  1.1626 +/*
  1.1627 +** sqlite3async_enable ?YES/NO?
  1.1628 +**
  1.1629 +** Enable or disable the asynchronous I/O backend.  This command is
  1.1630 +** not thread-safe.  Do not call it while any database connections
  1.1631 +** are open.
  1.1632 +*/
  1.1633 +static int testAsyncEnable(
  1.1634 +  void * clientData,
  1.1635 +  Tcl_Interp *interp,
  1.1636 +  int objc,
  1.1637 +  Tcl_Obj *CONST objv[]
  1.1638 +){
  1.1639 +  if( objc!=1 && objc!=2 ){
  1.1640 +    Tcl_WrongNumArgs(interp, 1, objv, "?YES/NO?");
  1.1641 +    return TCL_ERROR;
  1.1642 +  }
  1.1643 +  if( objc==1 ){
  1.1644 +    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(async_vfs.pAppData!=0));
  1.1645 +  }else{
  1.1646 +    int en;
  1.1647 +    if( Tcl_GetBooleanFromObj(interp, objv[1], &en) ) return TCL_ERROR;
  1.1648 +    asyncEnable(en);
  1.1649 +  }
  1.1650 +  return TCL_OK;
  1.1651 +}
  1.1652 +
  1.1653 +/*
  1.1654 +** sqlite3async_halt  "now"|"idle"|"never"
  1.1655 +**
  1.1656 +** Set the conditions at which the writer thread will halt.
  1.1657 +*/
  1.1658 +static int testAsyncHalt(
  1.1659 +  void * clientData,
  1.1660 +  Tcl_Interp *interp,
  1.1661 +  int objc,
  1.1662 +  Tcl_Obj *CONST objv[]
  1.1663 +){
  1.1664 +  const char *zCond;
  1.1665 +  if( objc!=2 ){
  1.1666 +    Tcl_WrongNumArgs(interp, 1, objv, "\"now\"|\"idle\"|\"never\"");
  1.1667 +    return TCL_ERROR;
  1.1668 +  }
  1.1669 +  zCond = Tcl_GetString(objv[1]);
  1.1670 +  if( strcmp(zCond, "now")==0 ){
  1.1671 +    async.writerHaltNow = 1;
  1.1672 +    pthread_cond_broadcast(&async.queueSignal);
  1.1673 +  }else if( strcmp(zCond, "idle")==0 ){
  1.1674 +    async.writerHaltWhenIdle = 1;
  1.1675 +    async.writerHaltNow = 0;
  1.1676 +    pthread_cond_broadcast(&async.queueSignal);
  1.1677 +  }else if( strcmp(zCond, "never")==0 ){
  1.1678 +    async.writerHaltWhenIdle = 0;
  1.1679 +    async.writerHaltNow = 0;
  1.1680 +  }else{
  1.1681 +    Tcl_AppendResult(interp, 
  1.1682 +      "should be one of: \"now\", \"idle\", or \"never\"", (char*)0);
  1.1683 +    return TCL_ERROR;
  1.1684 +  }
  1.1685 +  return TCL_OK;
  1.1686 +}
  1.1687 +
  1.1688 +/*
  1.1689 +** sqlite3async_delay ?MS?
  1.1690 +**
  1.1691 +** Query or set the number of milliseconds of delay in the writer
  1.1692 +** thread after each write operation.  The default is 0.  By increasing
  1.1693 +** the memory delay we can simulate the effect of slow disk I/O.
  1.1694 +*/
  1.1695 +static int testAsyncDelay(
  1.1696 +  void * clientData,
  1.1697 +  Tcl_Interp *interp,
  1.1698 +  int objc,
  1.1699 +  Tcl_Obj *CONST objv[]
  1.1700 +){
  1.1701 +  if( objc!=1 && objc!=2 ){
  1.1702 +    Tcl_WrongNumArgs(interp, 1, objv, "?MS?");
  1.1703 +    return TCL_ERROR;
  1.1704 +  }
  1.1705 +  if( objc==1 ){
  1.1706 +    Tcl_SetObjResult(interp, Tcl_NewIntObj(async.ioDelay));
  1.1707 +  }else{
  1.1708 +    int ioDelay;
  1.1709 +    if( Tcl_GetIntFromObj(interp, objv[1], &ioDelay) ) return TCL_ERROR;
  1.1710 +    async.ioDelay = ioDelay;
  1.1711 +  }
  1.1712 +  return TCL_OK;
  1.1713 +}
  1.1714 +
  1.1715 +/*
  1.1716 +** sqlite3async_start
  1.1717 +**
  1.1718 +** Start a new writer thread.
  1.1719 +*/
  1.1720 +static int testAsyncStart(
  1.1721 +  void * clientData,
  1.1722 +  Tcl_Interp *interp,
  1.1723 +  int objc,
  1.1724 +  Tcl_Obj *CONST objv[]
  1.1725 +){
  1.1726 +  pthread_t x;
  1.1727 +  int rc;
  1.1728 +  volatile int isStarted = 0;
  1.1729 +  rc = pthread_create(&x, 0, asyncWriterThread, (void *)&isStarted);
  1.1730 +  if( rc ){
  1.1731 +    Tcl_AppendResult(interp, "failed to create the thread", 0);
  1.1732 +    return TCL_ERROR;
  1.1733 +  }
  1.1734 +  pthread_detach(x);
  1.1735 +  while( isStarted==0 ){
  1.1736 +    sched_yield();
  1.1737 +  }
  1.1738 +  return TCL_OK;
  1.1739 +}
  1.1740 +
  1.1741 +/*
  1.1742 +** sqlite3async_wait
  1.1743 +**
  1.1744 +** Wait for the current writer thread to terminate.
  1.1745 +**
  1.1746 +** If the current writer thread is set to run forever then this
  1.1747 +** command would block forever.  To prevent that, an error is returned. 
  1.1748 +*/
  1.1749 +static int testAsyncWait(
  1.1750 +  void * clientData,
  1.1751 +  Tcl_Interp *interp,
  1.1752 +  int objc,
  1.1753 +  Tcl_Obj *CONST objv[]
  1.1754 +){
  1.1755 +  int cnt = 10;
  1.1756 +  if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){
  1.1757 +    Tcl_AppendResult(interp, "would block forever", (char*)0);
  1.1758 +    return TCL_ERROR;
  1.1759 +  }
  1.1760 +
  1.1761 +  while( cnt-- && !pthread_mutex_trylock(&async.writerMutex) ){
  1.1762 +    pthread_mutex_unlock(&async.writerMutex);
  1.1763 +    sched_yield();
  1.1764 +  }
  1.1765 +  if( cnt>=0 ){
  1.1766 +    ASYNC_TRACE(("WAIT\n"));
  1.1767 +    pthread_mutex_lock(&async.queueMutex);
  1.1768 +    pthread_cond_broadcast(&async.queueSignal);
  1.1769 +    pthread_mutex_unlock(&async.queueMutex);
  1.1770 +    pthread_mutex_lock(&async.writerMutex);
  1.1771 +    pthread_mutex_unlock(&async.writerMutex);
  1.1772 +  }else{
  1.1773 +    ASYNC_TRACE(("NO-WAIT\n"));
  1.1774 +  }
  1.1775 +  return TCL_OK;
  1.1776 +}
  1.1777 +
  1.1778 +
  1.1779 +#endif  /* SQLITE_OS_UNIX and SQLITE_THREADSAFE */
  1.1780 +
  1.1781 +/*
  1.1782 +** This routine registers the custom TCL commands defined in this
  1.1783 +** module.  This should be the only procedure visible from outside
  1.1784 +** of this module.
  1.1785 +*/
  1.1786 +int Sqlitetestasync_Init(Tcl_Interp *interp){
  1.1787 +#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
  1.1788 +  Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0);
  1.1789 +  Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0);
  1.1790 +  Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0);
  1.1791 +  Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);
  1.1792 +  Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);
  1.1793 +  Tcl_LinkVar(interp, "sqlite3async_trace",
  1.1794 +      (char*)&sqlite3async_trace, TCL_LINK_INT);
  1.1795 +#endif  /* SQLITE_OS_UNIX and SQLITE_THREADSAFE */
  1.1796 +  return TCL_OK;
  1.1797 +}