Annotation of embedaddon/sqlite3/ext/async/sqlite3async.c, revision 1.1

1.1     ! misho       1: /*
        !             2: ** 2005 December 14
        !             3: **
        !             4: ** The author disclaims copyright to this source code.  In place of
        !             5: ** a legal notice, here is a blessing:
        !             6: **
        !             7: **    May you do good and not evil.
        !             8: **    May you find forgiveness for yourself and forgive others.
        !             9: **    May you share freely, never taking more than you give.
        !            10: **
        !            11: *************************************************************************
        !            12: **
        !            13: ** $Id: sqlite3async.c,v 1.7 2009/07/18 11:52:04 danielk1977 Exp $
        !            14: **
        !            15: ** This file contains the implementation of an asynchronous IO backend 
        !            16: ** for SQLite.
        !            17: */
        !            18: 
        !            19: #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO)
        !            20: 
        !            21: #include "sqlite3async.h"
        !            22: #include "sqlite3.h"
        !            23: #include <stdarg.h>
        !            24: #include <string.h>
        !            25: #include <assert.h>
        !            26: 
        !            27: /* Useful macros used in several places */
        !            28: #define MIN(x,y) ((x)<(y)?(x):(y))
        !            29: #define MAX(x,y) ((x)>(y)?(x):(y))
        !            30: 
        !            31: #ifndef SQLITE_AMALGAMATION
        !            32: /* Macro to mark parameters as unused and silence compiler warnings. */
        !            33: #define UNUSED_PARAMETER(x) (void)(x)
        !            34: #endif
        !            35: 
        !            36: /* Forward references */
        !            37: typedef struct AsyncWrite AsyncWrite;
        !            38: typedef struct AsyncFile AsyncFile;
        !            39: typedef struct AsyncFileData AsyncFileData;
        !            40: typedef struct AsyncFileLock AsyncFileLock;
        !            41: typedef struct AsyncLock AsyncLock;
        !            42: 
        !            43: /* Enable for debugging */
        !            44: #ifndef NDEBUG
        !            45: #include <stdio.h>
        !            46: static int sqlite3async_trace = 0;
        !            47: # define ASYNC_TRACE(X) if( sqlite3async_trace ) asyncTrace X
        !            48: static void asyncTrace(const char *zFormat, ...){
        !            49:   char *z;
        !            50:   va_list ap;
        !            51:   va_start(ap, zFormat);
        !            52:   z = sqlite3_vmprintf(zFormat, ap);
        !            53:   va_end(ap);
        !            54:   fprintf(stderr, "[%d] %s", 0 /* (int)pthread_self() */, z);
        !            55:   sqlite3_free(z);
        !            56: }
        !            57: #else
        !            58: # define ASYNC_TRACE(X)
        !            59: #endif
        !            60: 
        !            61: /*
        !            62: ** THREAD SAFETY NOTES
        !            63: **
        !            64: ** Basic rules:
        !            65: **
        !            66: **     * Both read and write access to the global write-op queue must be 
        !            67: **       protected by the async.queueMutex. As are the async.ioError and
        !            68: **       async.nFile variables.
        !            69: **
        !            70: **     * The async.pLock list and all AsyncLock and AsyncFileLock
        !            71: **       structures must be protected by the async.lockMutex mutex.
        !            72: **
        !            73: **     * The file handles from the underlying system are not assumed to 
        !            74: **       be thread safe.
        !            75: **
        !            76: **     * See the last two paragraphs under "The Writer Thread" for
        !            77: **       an assumption to do with file-handle synchronization by the Os.
        !            78: **
        !            79: ** Deadlock prevention:
        !            80: **
        !            81: **     There are three mutex used by the system: the "writer" mutex, 
        !            82: **     the "queue" mutex and the "lock" mutex. Rules are:
        !            83: **
        !            84: **     * It is illegal to block on the writer mutex when any other mutex
        !            85: **       are held, and 
        !            86: **
        !            87: **     * It is illegal to block on the queue mutex when the lock mutex
        !            88: **       is held.
        !            89: **
        !            90: **     i.e. mutex's must be grabbed in the order "writer", "queue", "lock".
        !            91: **
        !            92: ** File system operations (invoked by SQLite thread):
        !            93: **
        !            94: **     xOpen
        !            95: **     xDelete
        !            96: **     xFileExists
        !            97: **
        !            98: ** File handle operations (invoked by SQLite thread):
        !            99: **
        !           100: **         asyncWrite, asyncClose, asyncTruncate, asyncSync 
        !           101: **    
        !           102: **     The operations above add an entry to the global write-op list. They
        !           103: **     prepare the entry, acquire the async.queueMutex momentarily while
        !           104: **     list pointers are  manipulated to insert the new entry, then release
        !           105: **     the mutex and signal the writer thread to wake up in case it happens
        !           106: **     to be asleep.
        !           107: **
        !           108: **    
        !           109: **         asyncRead, asyncFileSize.
        !           110: **
        !           111: **     Read operations. Both of these read from both the underlying file
        !           112: **     first then adjust their result based on pending writes in the 
        !           113: **     write-op queue.   So async.queueMutex is held for the duration
        !           114: **     of these operations to prevent other threads from changing the
        !           115: **     queue in mid operation.
        !           116: **    
        !           117: **
        !           118: **         asyncLock, asyncUnlock, asyncCheckReservedLock
        !           119: **    
        !           120: **     These primitives implement in-process locking using a hash table
        !           121: **     on the file name.  Files are locked correctly for connections coming
        !           122: **     from the same process.  But other processes cannot see these locks
        !           123: **     and will therefore not honor them.
        !           124: **
        !           125: **
        !           126: ** The writer thread:
        !           127: **
        !           128: **     The async.writerMutex is used to make sure only there is only
        !           129: **     a single writer thread running at a time.
        !           130: **
        !           131: **     Inside the writer thread is a loop that works like this:
        !           132: **
        !           133: **         WHILE (write-op list is not empty)
        !           134: **             Do IO operation at head of write-op list
        !           135: **             Remove entry from head of write-op list
        !           136: **         END WHILE
        !           137: **
        !           138: **     The async.queueMutex is always held during the <write-op list is 
        !           139: **     not empty> test, and when the entry is removed from the head
        !           140: **     of the write-op list. Sometimes it is held for the interim
        !           141: **     period (while the IO is performed), and sometimes it is
        !           142: **     relinquished. It is relinquished if (a) the IO op is an
        !           143: **     ASYNC_CLOSE or (b) when the file handle was opened, two of
        !           144: **     the underlying systems handles were opened on the same
        !           145: **     file-system entry.
        !           146: **
        !           147: **     If condition (b) above is true, then one file-handle 
        !           148: **     (AsyncFile.pBaseRead) is used exclusively by sqlite threads to read the
        !           149: **     file, the other (AsyncFile.pBaseWrite) by sqlite3_async_flush() 
        !           150: **     threads to perform write() operations. This means that read 
        !           151: **     operations are not blocked by asynchronous writes (although 
        !           152: **     asynchronous writes may still be blocked by reads).
        !           153: **
        !           154: **     This assumes that the OS keeps two handles open on the same file
        !           155: **     properly in sync. That is, any read operation that starts after a
        !           156: **     write operation on the same file system entry has completed returns
        !           157: **     data consistent with the write. We also assume that if one thread 
        !           158: **     reads a file while another is writing it all bytes other than the
        !           159: **     ones actually being written contain valid data.
        !           160: **
        !           161: **     If the above assumptions are not true, set the preprocessor symbol
        !           162: **     SQLITE_ASYNC_TWO_FILEHANDLES to 0.
        !           163: */
        !           164: 
        !           165: 
        !           166: #ifndef NDEBUG
        !           167: # define TESTONLY( X ) X
        !           168: #else
        !           169: # define TESTONLY( X )
        !           170: #endif
        !           171: 
        !           172: /*
        !           173: ** PORTING FUNCTIONS
        !           174: **
        !           175: ** There are two definitions of the following functions. One for pthreads
        !           176: ** compatible systems and one for Win32. These functions isolate the OS
        !           177: ** specific code required by each platform.
        !           178: **
        !           179: ** The system uses three mutexes and a single condition variable. To
        !           180: ** block on a mutex, async_mutex_enter() is called. The parameter passed
        !           181: ** to async_mutex_enter(), which must be one of ASYNC_MUTEX_LOCK,
        !           182: ** ASYNC_MUTEX_QUEUE or ASYNC_MUTEX_WRITER, identifies which of the three
        !           183: ** mutexes to lock. Similarly, to unlock a mutex, async_mutex_leave() is
        !           184: ** called with a parameter identifying the mutex being unlocked. Mutexes
        !           185: ** are not recursive - it is an error to call async_mutex_enter() to
        !           186: ** lock a mutex that is already locked, or to call async_mutex_leave()
        !           187: ** to unlock a mutex that is not currently locked.
        !           188: **
        !           189: ** The async_cond_wait() and async_cond_signal() functions are modelled
        !           190: ** on the pthreads functions with similar names. The first parameter to
        !           191: ** both functions is always ASYNC_COND_QUEUE. When async_cond_wait()
        !           192: ** is called the mutex identified by the second parameter must be held.
        !           193: ** The mutex is unlocked, and the calling thread simultaneously begins 
        !           194: ** waiting for the condition variable to be signalled by another thread.
        !           195: ** After another thread signals the condition variable, the calling
        !           196: ** thread stops waiting, locks mutex eMutex and returns. The 
        !           197: ** async_cond_signal() function is used to signal the condition variable. 
        !           198: ** It is assumed that the mutex used by the thread calling async_cond_wait() 
        !           199: ** is held by the caller of async_cond_signal() (otherwise there would be 
        !           200: ** a race condition).
        !           201: **
        !           202: ** It is guaranteed that no other thread will call async_cond_wait() when
        !           203: ** there is already a thread waiting on the condition variable.
        !           204: **
        !           205: ** The async_sched_yield() function is called to suggest to the operating
        !           206: ** system that it would be a good time to shift the current thread off the
        !           207: ** CPU. The system will still work if this function is not implemented
        !           208: ** (it is not currently implemented for win32), but it might be marginally
        !           209: ** more efficient if it is.
        !           210: */
        !           211: static void async_mutex_enter(int eMutex);
        !           212: static void async_mutex_leave(int eMutex);
        !           213: static void async_cond_wait(int eCond, int eMutex);
        !           214: static void async_cond_signal(int eCond);
        !           215: static void async_sched_yield(void);
        !           216: 
        !           217: /*
        !           218: ** There are also two definitions of the following. async_os_initialize()
        !           219: ** is called when the asynchronous VFS is first installed, and os_shutdown()
        !           220: ** is called when it is uninstalled (from within sqlite3async_shutdown()).
        !           221: **
        !           222: ** For pthreads builds, both of these functions are no-ops. For win32,
        !           223: ** they provide an opportunity to initialize and finalize the required
        !           224: ** mutex and condition variables.
        !           225: **
        !           226: ** If async_os_initialize() returns other than zero, then the initialization
        !           227: ** fails and SQLITE_ERROR is returned to the user.
        !           228: */
        !           229: static int async_os_initialize(void);
        !           230: static void async_os_shutdown(void);
        !           231: 
        !           232: /* Values for use as the 'eMutex' argument of the above functions. The
        !           233: ** integer values assigned to these constants are important for assert()
        !           234: ** statements that verify that mutexes are locked in the correct order.
        !           235: ** Specifically, it is unsafe to try to lock mutex N while holding a lock 
        !           236: ** on mutex M if (M<=N).
        !           237: */
        !           238: #define ASYNC_MUTEX_LOCK    0
        !           239: #define ASYNC_MUTEX_QUEUE   1
        !           240: #define ASYNC_MUTEX_WRITER  2
        !           241: 
        !           242: /* Values for use as the 'eCond' argument of the above functions. */
        !           243: #define ASYNC_COND_QUEUE    0
        !           244: 
        !           245: /*************************************************************************
        !           246: ** Start of OS specific code.
        !           247: */
        !           248: #if SQLITE_OS_WIN || defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
        !           249: 
        !           250: #include <windows.h>
        !           251: 
        !           252: /* The following block contains the win32 specific code. */
        !           253: 
        !           254: #define mutex_held(X) (GetCurrentThreadId()==primitives.aHolder[X])
        !           255: 
        !           256: static struct AsyncPrimitives {
        !           257:   int isInit;
        !           258:   DWORD aHolder[3];
        !           259:   CRITICAL_SECTION aMutex[3];
        !           260:   HANDLE aCond[1];
        !           261: } primitives = { 0 };
        !           262: 
        !           263: static int async_os_initialize(void){
        !           264:   if( !primitives.isInit ){
        !           265:     primitives.aCond[0] = CreateEvent(NULL, TRUE, FALSE, 0);
        !           266:     if( primitives.aCond[0]==NULL ){
        !           267:       return 1;
        !           268:     }
        !           269:     InitializeCriticalSection(&primitives.aMutex[0]);
        !           270:     InitializeCriticalSection(&primitives.aMutex[1]);
        !           271:     InitializeCriticalSection(&primitives.aMutex[2]);
        !           272:     primitives.isInit = 1;
        !           273:   }
        !           274:   return 0;
        !           275: }
        !           276: static void async_os_shutdown(void){
        !           277:   if( primitives.isInit ){
        !           278:     DeleteCriticalSection(&primitives.aMutex[0]);
        !           279:     DeleteCriticalSection(&primitives.aMutex[1]);
        !           280:     DeleteCriticalSection(&primitives.aMutex[2]);
        !           281:     CloseHandle(primitives.aCond[0]);
        !           282:     primitives.isInit = 0;
        !           283:   }
        !           284: }
        !           285: 
        !           286: /* The following block contains the Win32 specific code. */
        !           287: static void async_mutex_enter(int eMutex){
        !           288:   assert( eMutex==0 || eMutex==1 || eMutex==2 );
        !           289:   assert( eMutex!=2 || (!mutex_held(0) && !mutex_held(1) && !mutex_held(2)) );
        !           290:   assert( eMutex!=1 || (!mutex_held(0) && !mutex_held(1)) );
        !           291:   assert( eMutex!=0 || (!mutex_held(0)) );
        !           292:   EnterCriticalSection(&primitives.aMutex[eMutex]);
        !           293:   TESTONLY( primitives.aHolder[eMutex] = GetCurrentThreadId(); )
        !           294: }
        !           295: static void async_mutex_leave(int eMutex){
        !           296:   assert( eMutex==0 || eMutex==1 || eMutex==2 );
        !           297:   assert( mutex_held(eMutex) );
        !           298:   TESTONLY( primitives.aHolder[eMutex] = 0; )
        !           299:   LeaveCriticalSection(&primitives.aMutex[eMutex]);
        !           300: }
        !           301: static void async_cond_wait(int eCond, int eMutex){
        !           302:   ResetEvent(primitives.aCond[eCond]);
        !           303:   async_mutex_leave(eMutex);
        !           304:   WaitForSingleObject(primitives.aCond[eCond], INFINITE);
        !           305:   async_mutex_enter(eMutex);
        !           306: }
        !           307: static void async_cond_signal(int eCond){
        !           308:   assert( mutex_held(ASYNC_MUTEX_QUEUE) );
        !           309:   SetEvent(primitives.aCond[eCond]);
        !           310: }
        !           311: static void async_sched_yield(void){
        !           312:   Sleep(0);
        !           313: }
        !           314: #else
        !           315: 
        !           316: /* The following block contains the pthreads specific code. */
        !           317: #include <pthread.h>
        !           318: #include <sched.h>
        !           319: 
        !           320: #define mutex_held(X) pthread_equal(primitives.aHolder[X], pthread_self())
        !           321: 
        !           322: static int  async_os_initialize(void) {return 0;}
        !           323: static void async_os_shutdown(void) {}
        !           324: 
        !           325: static struct AsyncPrimitives {
        !           326:   pthread_mutex_t aMutex[3];
        !           327:   pthread_cond_t aCond[1];
        !           328:   pthread_t aHolder[3];
        !           329: } primitives = {
        !           330:   { PTHREAD_MUTEX_INITIALIZER, 
        !           331:     PTHREAD_MUTEX_INITIALIZER, 
        !           332:     PTHREAD_MUTEX_INITIALIZER
        !           333:   } , {
        !           334:     PTHREAD_COND_INITIALIZER
        !           335:   } , { 0, 0, 0 }
        !           336: };
        !           337: 
        !           338: static void async_mutex_enter(int eMutex){
        !           339:   assert( eMutex==0 || eMutex==1 || eMutex==2 );
        !           340:   assert( eMutex!=2 || (!mutex_held(0) && !mutex_held(1) && !mutex_held(2)) );
        !           341:   assert( eMutex!=1 || (!mutex_held(0) && !mutex_held(1)) );
        !           342:   assert( eMutex!=0 || (!mutex_held(0)) );
        !           343:   pthread_mutex_lock(&primitives.aMutex[eMutex]);
        !           344:   TESTONLY( primitives.aHolder[eMutex] = pthread_self(); )
        !           345: }
        !           346: static void async_mutex_leave(int eMutex){
        !           347:   assert( eMutex==0 || eMutex==1 || eMutex==2 );
        !           348:   assert( mutex_held(eMutex) );
        !           349:   TESTONLY( primitives.aHolder[eMutex] = 0; )
        !           350:   pthread_mutex_unlock(&primitives.aMutex[eMutex]);
        !           351: }
        !           352: static void async_cond_wait(int eCond, int eMutex){
        !           353:   assert( eMutex==0 || eMutex==1 || eMutex==2 );
        !           354:   assert( mutex_held(eMutex) );
        !           355:   TESTONLY( primitives.aHolder[eMutex] = 0; )
        !           356:   pthread_cond_wait(&primitives.aCond[eCond], &primitives.aMutex[eMutex]);
        !           357:   TESTONLY( primitives.aHolder[eMutex] = pthread_self(); )
        !           358: }
        !           359: static void async_cond_signal(int eCond){
        !           360:   assert( mutex_held(ASYNC_MUTEX_QUEUE) );
        !           361:   pthread_cond_signal(&primitives.aCond[eCond]);
        !           362: }
        !           363: static void async_sched_yield(void){
        !           364:   sched_yield();
        !           365: }
        !           366: #endif
        !           367: /*
        !           368: ** End of OS specific code.
        !           369: *************************************************************************/
        !           370: 
        !           371: #define assert_mutex_is_held(X) assert( mutex_held(X) )
        !           372: 
        !           373: 
        !           374: #ifndef SQLITE_ASYNC_TWO_FILEHANDLES
        !           375: /* #define SQLITE_ASYNC_TWO_FILEHANDLES 0 */
        !           376: #define SQLITE_ASYNC_TWO_FILEHANDLES 1
        !           377: #endif
        !           378: 
        !           379: /*
        !           380: ** State information is held in the static variable "async" defined
        !           381: ** as the following structure.
        !           382: **
        !           383: ** Both async.ioError and async.nFile are protected by async.queueMutex.
        !           384: */
        !           385: static struct TestAsyncStaticData {
        !           386:   AsyncWrite *pQueueFirst;     /* Next write operation to be processed */
        !           387:   AsyncWrite *pQueueLast;      /* Last write operation on the list */
        !           388:   AsyncLock *pLock;            /* Linked list of all AsyncLock structures */
        !           389:   volatile int ioDelay;        /* Extra delay between write operations */
        !           390:   volatile int eHalt;          /* One of the SQLITEASYNC_HALT_XXX values */
        !           391:   volatile int bLockFiles;     /* Current value of "lockfiles" parameter */
        !           392:   int ioError;                 /* True if an IO error has occurred */
        !           393:   int nFile;                   /* Number of open files (from sqlite pov) */
        !           394: } async = { 0,0,0,0,0,1,0,0 };
        !           395: 
        !           396: /* Possible values of AsyncWrite.op */
        !           397: #define ASYNC_NOOP          0
        !           398: #define ASYNC_WRITE         1
        !           399: #define ASYNC_SYNC          2
        !           400: #define ASYNC_TRUNCATE      3
        !           401: #define ASYNC_CLOSE         4
        !           402: #define ASYNC_DELETE        5
        !           403: #define ASYNC_OPENEXCLUSIVE 6
        !           404: #define ASYNC_UNLOCK        7
        !           405: 
        !           406: /* Names of opcodes.  Used for debugging only.
        !           407: ** Make sure these stay in sync with the macros above!
        !           408: */
        !           409: static const char *azOpcodeName[] = {
        !           410:   "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE", "DELETE", "OPENEX", "UNLOCK"
        !           411: };
        !           412: 
        !           413: /*
        !           414: ** Entries on the write-op queue are instances of the AsyncWrite
        !           415: ** structure, defined here.
        !           416: **
        !           417: ** The interpretation of the iOffset and nByte variables varies depending 
        !           418: ** on the value of AsyncWrite.op:
        !           419: **
        !           420: ** ASYNC_NOOP:
        !           421: **     No values used.
        !           422: **
        !           423: ** ASYNC_WRITE:
        !           424: **     iOffset -> Offset in file to write to.
        !           425: **     nByte   -> Number of bytes of data to write (pointed to by zBuf).
        !           426: **
        !           427: ** ASYNC_SYNC:
        !           428: **     nByte   -> flags to pass to sqlite3OsSync().
        !           429: **
        !           430: ** ASYNC_TRUNCATE:
        !           431: **     iOffset -> Size to truncate file to.
        !           432: **     nByte   -> Unused.
        !           433: **
        !           434: ** ASYNC_CLOSE:
        !           435: **     iOffset -> Unused.
        !           436: **     nByte   -> Unused.
        !           437: **
        !           438: ** ASYNC_DELETE:
        !           439: **     iOffset -> Contains the "syncDir" flag.
        !           440: **     nByte   -> Number of bytes of zBuf points to (file name).
        !           441: **
        !           442: ** ASYNC_OPENEXCLUSIVE:
        !           443: **     iOffset -> Value of "delflag".
        !           444: **     nByte   -> Number of bytes of zBuf points to (file name).
        !           445: **
        !           446: ** ASYNC_UNLOCK:
        !           447: **     nByte   -> Argument to sqlite3OsUnlock().
        !           448: **
        !           449: **
        !           450: ** For an ASYNC_WRITE operation, zBuf points to the data to write to the file. 
        !           451: ** This space is sqlite3_malloc()d along with the AsyncWrite structure in a
        !           452: ** single blob, so is deleted when sqlite3_free() is called on the parent 
        !           453: ** structure.
        !           454: */
        !           455: struct AsyncWrite {
        !           456:   AsyncFileData *pFileData;    /* File to write data to or sync */
        !           457:   int op;                      /* One of ASYNC_xxx etc. */
        !           458:   sqlite_int64 iOffset;        /* See above */
        !           459:   int nByte;          /* See above */
        !           460:   char *zBuf;         /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
        !           461:   AsyncWrite *pNext;  /* Next write operation (to any file) */
        !           462: };
        !           463: 
        !           464: /*
        !           465: ** An instance of this structure is created for each distinct open file 
        !           466: ** (i.e. if two handles are opened on the one file, only one of these
        !           467: ** structures is allocated) and stored in the async.aLock hash table. The
        !           468: ** keys for async.aLock are the full pathnames of the opened files.
        !           469: **
        !           470: ** AsyncLock.pList points to the head of a linked list of AsyncFileLock
        !           471: ** structures, one for each handle currently open on the file.
        !           472: **
        !           473: ** If the opened file is not a main-database (the SQLITE_OPEN_MAIN_DB is
        !           474: ** not passed to the sqlite3OsOpen() call), or if async.bLockFiles is 
        !           475: ** false, variables AsyncLock.pFile and AsyncLock.eLock are never used. 
        !           476: ** Otherwise, pFile is a file handle opened on the file in question and 
        !           477: ** used to obtain the file-system locks required by database connections 
        !           478: ** within this process.
        !           479: **
        !           480: ** See comments above the asyncLock() function for more details on 
        !           481: ** the implementation of database locking used by this backend.
        !           482: */
        !           483: struct AsyncLock {
        !           484:   char *zFile;
        !           485:   int nFile;
        !           486:   sqlite3_file *pFile;
        !           487:   int eLock;
        !           488:   AsyncFileLock *pList;
        !           489:   AsyncLock *pNext;           /* Next in linked list headed by async.pLock */
        !           490: };
        !           491: 
        !           492: /*
        !           493: ** An instance of the following structure is allocated along with each
        !           494: ** AsyncFileData structure (see AsyncFileData.lock), but is only used if the
        !           495: ** file was opened with the SQLITE_OPEN_MAIN_DB.
        !           496: */
        !           497: struct AsyncFileLock {
        !           498:   int eLock;                /* Internally visible lock state (sqlite pov) */
        !           499:   int eAsyncLock;           /* Lock-state with write-queue unlock */
        !           500:   AsyncFileLock *pNext;
        !           501: };
        !           502: 
        !           503: /* 
        !           504: ** The AsyncFile structure is a subclass of sqlite3_file used for 
        !           505: ** asynchronous IO. 
        !           506: **
        !           507: ** All of the actual data for the structure is stored in the structure
        !           508: ** pointed to by AsyncFile.pData, which is allocated as part of the
        !           509: ** sqlite3OsOpen() using sqlite3_malloc(). The reason for this is that the
        !           510: ** lifetime of the AsyncFile structure is ended by the caller after OsClose()
        !           511: ** is called, but the data in AsyncFileData may be required by the
        !           512: ** writer thread after that point.
        !           513: */
        !           514: struct AsyncFile {
        !           515:   sqlite3_io_methods *pMethod;
        !           516:   AsyncFileData *pData;
        !           517: };
        !           518: struct AsyncFileData {
        !           519:   char *zName;               /* Underlying OS filename - used for debugging */
        !           520:   int nName;                 /* Number of characters in zName */
        !           521:   sqlite3_file *pBaseRead;   /* Read handle to the underlying Os file */
        !           522:   sqlite3_file *pBaseWrite;  /* Write handle to the underlying Os file */
        !           523:   AsyncFileLock lock;        /* Lock state for this handle */
        !           524:   AsyncLock *pLock;          /* AsyncLock object for this file system entry */
        !           525:   AsyncWrite closeOp;        /* Preallocated close operation */
        !           526: };
        !           527: 
        !           528: /*
        !           529: ** Add an entry to the end of the global write-op list. pWrite should point 
        !           530: ** to an AsyncWrite structure allocated using sqlite3_malloc().  The writer
        !           531: ** thread will call sqlite3_free() to free the structure after the specified
        !           532: ** operation has been completed.
        !           533: **
        !           534: ** Once an AsyncWrite structure has been added to the list, it becomes the
        !           535: ** property of the writer thread and must not be read or modified by the
        !           536: ** caller.  
        !           537: */
        !           538: static void addAsyncWrite(AsyncWrite *pWrite){
        !           539:   /* We must hold the queue mutex in order to modify the queue pointers */
        !           540:   if( pWrite->op!=ASYNC_UNLOCK ){
        !           541:     async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !           542:   }
        !           543: 
        !           544:   /* Add the record to the end of the write-op queue */
        !           545:   assert( !pWrite->pNext );
        !           546:   if( async.pQueueLast ){
        !           547:     assert( async.pQueueFirst );
        !           548:     async.pQueueLast->pNext = pWrite;
        !           549:   }else{
        !           550:     async.pQueueFirst = pWrite;
        !           551:   }
        !           552:   async.pQueueLast = pWrite;
        !           553:   ASYNC_TRACE(("PUSH %p (%s %s %d)\n", pWrite, azOpcodeName[pWrite->op],
        !           554:          pWrite->pFileData ? pWrite->pFileData->zName : "-", pWrite->iOffset));
        !           555: 
        !           556:   if( pWrite->op==ASYNC_CLOSE ){
        !           557:     async.nFile--;
        !           558:   }
        !           559: 
        !           560:   /* The writer thread might have been idle because there was nothing
        !           561:   ** on the write-op queue for it to do.  So wake it up. */
        !           562:   async_cond_signal(ASYNC_COND_QUEUE);
        !           563: 
        !           564:   /* Drop the queue mutex */
        !           565:   if( pWrite->op!=ASYNC_UNLOCK ){
        !           566:     async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !           567:   }
        !           568: }
        !           569: 
        !           570: /*
        !           571: ** Increment async.nFile in a thread-safe manner.
        !           572: */
        !           573: static void incrOpenFileCount(void){
        !           574:   /* We must hold the queue mutex in order to modify async.nFile */
        !           575:   async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !           576:   if( async.nFile==0 ){
        !           577:     async.ioError = SQLITE_OK;
        !           578:   }
        !           579:   async.nFile++;
        !           580:   async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !           581: }
        !           582: 
        !           583: /*
        !           584: ** This is a utility function to allocate and populate a new AsyncWrite
        !           585: ** structure and insert it (via addAsyncWrite() ) into the global list.
        !           586: */
        !           587: static int addNewAsyncWrite(
        !           588:   AsyncFileData *pFileData, 
        !           589:   int op, 
        !           590:   sqlite3_int64 iOffset, 
        !           591:   int nByte,
        !           592:   const char *zByte
        !           593: ){
        !           594:   AsyncWrite *p;
        !           595:   if( op!=ASYNC_CLOSE && async.ioError ){
        !           596:     return async.ioError;
        !           597:   }
        !           598:   p = sqlite3_malloc(sizeof(AsyncWrite) + (zByte?nByte:0));
        !           599:   if( !p ){
        !           600:     /* The upper layer does not expect operations like OsWrite() to
        !           601:     ** return SQLITE_NOMEM. This is partly because under normal conditions
        !           602:     ** SQLite is required to do rollback without calling malloc(). So
        !           603:     ** if malloc() fails here, treat it as an I/O error. The above
        !           604:     ** layer knows how to handle that.
        !           605:     */
        !           606:     return SQLITE_IOERR;
        !           607:   }
        !           608:   p->op = op;
        !           609:   p->iOffset = iOffset;
        !           610:   p->nByte = nByte;
        !           611:   p->pFileData = pFileData;
        !           612:   p->pNext = 0;
        !           613:   if( zByte ){
        !           614:     p->zBuf = (char *)&p[1];
        !           615:     memcpy(p->zBuf, zByte, nByte);
        !           616:   }else{
        !           617:     p->zBuf = 0;
        !           618:   }
        !           619:   addAsyncWrite(p);
        !           620:   return SQLITE_OK;
        !           621: }
        !           622: 
        !           623: /*
        !           624: ** Close the file. This just adds an entry to the write-op list, the file is
        !           625: ** not actually closed.
        !           626: */
        !           627: static int asyncClose(sqlite3_file *pFile){
        !           628:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           629: 
        !           630:   /* Unlock the file, if it is locked */
        !           631:   async_mutex_enter(ASYNC_MUTEX_LOCK);
        !           632:   p->lock.eLock = 0;
        !           633:   async_mutex_leave(ASYNC_MUTEX_LOCK);
        !           634: 
        !           635:   addAsyncWrite(&p->closeOp);
        !           636:   return SQLITE_OK;
        !           637: }
        !           638: 
        !           639: /*
        !           640: ** Implementation of sqlite3OsWrite() for asynchronous files. Instead of 
        !           641: ** writing to the underlying file, this function adds an entry to the end of
        !           642: ** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
        !           643: ** returned.
        !           644: */
        !           645: static int asyncWrite(
        !           646:   sqlite3_file *pFile, 
        !           647:   const void *pBuf, 
        !           648:   int amt, 
        !           649:   sqlite3_int64 iOff
        !           650: ){
        !           651:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           652:   return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf);
        !           653: }
        !           654: 
        !           655: /*
        !           656: ** Read data from the file. First we read from the filesystem, then adjust 
        !           657: ** the contents of the buffer based on ASYNC_WRITE operations in the 
        !           658: ** write-op queue.
        !           659: **
        !           660: ** This method holds the mutex from start to finish.
        !           661: */
        !           662: static int asyncRead(
        !           663:   sqlite3_file *pFile, 
        !           664:   void *zOut, 
        !           665:   int iAmt, 
        !           666:   sqlite3_int64 iOffset
        !           667: ){
        !           668:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           669:   int rc = SQLITE_OK;
        !           670:   sqlite3_int64 filesize = 0;
        !           671:   sqlite3_file *pBase = p->pBaseRead;
        !           672:   sqlite3_int64 iAmt64 = (sqlite3_int64)iAmt;
        !           673: 
        !           674:   /* Grab the write queue mutex for the duration of the call */
        !           675:   async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !           676: 
        !           677:   /* If an I/O error has previously occurred in this virtual file 
        !           678:   ** system, then all subsequent operations fail.
        !           679:   */
        !           680:   if( async.ioError!=SQLITE_OK ){
        !           681:     rc = async.ioError;
        !           682:     goto asyncread_out;
        !           683:   }
        !           684: 
        !           685:   if( pBase->pMethods ){
        !           686:     sqlite3_int64 nRead;
        !           687:     rc = pBase->pMethods->xFileSize(pBase, &filesize);
        !           688:     if( rc!=SQLITE_OK ){
        !           689:       goto asyncread_out;
        !           690:     }
        !           691:     nRead = MIN(filesize - iOffset, iAmt64);
        !           692:     if( nRead>0 ){
        !           693:       rc = pBase->pMethods->xRead(pBase, zOut, (int)nRead, iOffset);
        !           694:       ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset));
        !           695:     }
        !           696:   }
        !           697: 
        !           698:   if( rc==SQLITE_OK ){
        !           699:     AsyncWrite *pWrite;
        !           700:     char *zName = p->zName;
        !           701: 
        !           702:     for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
        !           703:       if( pWrite->op==ASYNC_WRITE && (
        !           704:         (pWrite->pFileData==p) ||
        !           705:         (zName && pWrite->pFileData->zName==zName)
        !           706:       )){
        !           707:         sqlite3_int64 nCopy;
        !           708:         sqlite3_int64 nByte64 = (sqlite3_int64)pWrite->nByte;
        !           709: 
        !           710:         /* Set variable iBeginIn to the offset in buffer pWrite->zBuf[] from
        !           711:         ** which data should be copied. Set iBeginOut to the offset within
        !           712:         ** the output buffer to which data should be copied. If either of
        !           713:         ** these offsets is a negative number, set them to 0.
        !           714:         */
        !           715:         sqlite3_int64 iBeginOut = (pWrite->iOffset-iOffset);
        !           716:         sqlite3_int64 iBeginIn = -iBeginOut;
        !           717:         if( iBeginIn<0 ) iBeginIn = 0;
        !           718:         if( iBeginOut<0 ) iBeginOut = 0;
        !           719: 
        !           720:         filesize = MAX(filesize, pWrite->iOffset+nByte64);
        !           721: 
        !           722:         nCopy = MIN(nByte64-iBeginIn, iAmt64-iBeginOut);
        !           723:         if( nCopy>0 ){
        !           724:           memcpy(&((char *)zOut)[iBeginOut], &pWrite->zBuf[iBeginIn], (size_t)nCopy);
        !           725:           ASYNC_TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset));
        !           726:         }
        !           727:       }
        !           728:     }
        !           729:   }
        !           730: 
        !           731: asyncread_out:
        !           732:   async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !           733:   if( rc==SQLITE_OK && filesize<(iOffset+iAmt) ){
        !           734:     rc = SQLITE_IOERR_SHORT_READ;
        !           735:   }
        !           736:   return rc;
        !           737: }
        !           738: 
        !           739: /*
        !           740: ** Truncate the file to nByte bytes in length. This just adds an entry to 
        !           741: ** the write-op list, no IO actually takes place.
        !           742: */
        !           743: static int asyncTruncate(sqlite3_file *pFile, sqlite3_int64 nByte){
        !           744:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           745:   return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0);
        !           746: }
        !           747: 
        !           748: /*
        !           749: ** Sync the file. This just adds an entry to the write-op list, the 
        !           750: ** sync() is done later by sqlite3_async_flush().
        !           751: */
        !           752: static int asyncSync(sqlite3_file *pFile, int flags){
        !           753:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           754:   return addNewAsyncWrite(p, ASYNC_SYNC, 0, flags, 0);
        !           755: }
        !           756: 
        !           757: /*
        !           758: ** Read the size of the file. First we read the size of the file system 
        !           759: ** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations 
        !           760: ** currently in the write-op list. 
        !           761: **
        !           762: ** This method holds the mutex from start to finish.
        !           763: */
        !           764: int asyncFileSize(sqlite3_file *pFile, sqlite3_int64 *piSize){
        !           765:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           766:   int rc = SQLITE_OK;
        !           767:   sqlite3_int64 s = 0;
        !           768:   sqlite3_file *pBase;
        !           769: 
        !           770:   async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !           771: 
        !           772:   /* Read the filesystem size from the base file. If pMethods is NULL, this
        !           773:   ** means the file hasn't been opened yet. In this case all relevant data 
        !           774:   ** must be in the write-op queue anyway, so we can omit reading from the
        !           775:   ** file-system.
        !           776:   */
        !           777:   pBase = p->pBaseRead;
        !           778:   if( pBase->pMethods ){
        !           779:     rc = pBase->pMethods->xFileSize(pBase, &s);
        !           780:   }
        !           781: 
        !           782:   if( rc==SQLITE_OK ){
        !           783:     AsyncWrite *pWrite;
        !           784:     for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
        !           785:       if( pWrite->op==ASYNC_DELETE 
        !           786:        && p->zName 
        !           787:        && strcmp(p->zName, pWrite->zBuf)==0 
        !           788:       ){
        !           789:         s = 0;
        !           790:       }else if( pWrite->pFileData && (
        !           791:           (pWrite->pFileData==p) 
        !           792:        || (p->zName && pWrite->pFileData->zName==p->zName) 
        !           793:       )){
        !           794:         switch( pWrite->op ){
        !           795:           case ASYNC_WRITE:
        !           796:             s = MAX(pWrite->iOffset + (sqlite3_int64)(pWrite->nByte), s);
        !           797:             break;
        !           798:           case ASYNC_TRUNCATE:
        !           799:             s = MIN(s, pWrite->iOffset);
        !           800:             break;
        !           801:         }
        !           802:       }
        !           803:     }
        !           804:     *piSize = s;
        !           805:   }
        !           806:   async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !           807:   return rc;
        !           808: }
        !           809: 
        !           810: /*
        !           811: ** Lock or unlock the actual file-system entry.
        !           812: */
        !           813: static int getFileLock(AsyncLock *pLock){
        !           814:   int rc = SQLITE_OK;
        !           815:   AsyncFileLock *pIter;
        !           816:   int eRequired = 0;
        !           817: 
        !           818:   if( pLock->pFile ){
        !           819:     for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
        !           820:       assert(pIter->eAsyncLock>=pIter->eLock);
        !           821:       if( pIter->eAsyncLock>eRequired ){
        !           822:         eRequired = pIter->eAsyncLock;
        !           823:         assert(eRequired>=0 && eRequired<=SQLITE_LOCK_EXCLUSIVE);
        !           824:       }
        !           825:     }
        !           826: 
        !           827:     if( eRequired>pLock->eLock ){
        !           828:       rc = pLock->pFile->pMethods->xLock(pLock->pFile, eRequired);
        !           829:       if( rc==SQLITE_OK ){
        !           830:         pLock->eLock = eRequired;
        !           831:       }
        !           832:     }
        !           833:     else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){
        !           834:       rc = pLock->pFile->pMethods->xUnlock(pLock->pFile, eRequired);
        !           835:       if( rc==SQLITE_OK ){
        !           836:         pLock->eLock = eRequired;
        !           837:       }
        !           838:     }
        !           839:   }
        !           840: 
        !           841:   return rc;
        !           842: }
        !           843: 
        !           844: /*
        !           845: ** Return the AsyncLock structure from the global async.pLock list 
        !           846: ** associated with the file-system entry identified by path zName 
        !           847: ** (a string of nName bytes). If no such structure exists, return 0.
        !           848: */
        !           849: static AsyncLock *findLock(const char *zName, int nName){
        !           850:   AsyncLock *p = async.pLock;
        !           851:   while( p && (p->nFile!=nName || memcmp(p->zFile, zName, nName)) ){
        !           852:     p = p->pNext;
        !           853:   }
        !           854:   return p;
        !           855: }
        !           856: 
        !           857: /*
        !           858: ** The following two methods - asyncLock() and asyncUnlock() - are used
        !           859: ** to obtain and release locks on database files opened with the
        !           860: ** asynchronous backend.
        !           861: */
        !           862: static int asyncLock(sqlite3_file *pFile, int eLock){
        !           863:   int rc = SQLITE_OK;
        !           864:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           865: 
        !           866:   if( p->zName ){
        !           867:     async_mutex_enter(ASYNC_MUTEX_LOCK);
        !           868:     if( p->lock.eLock<eLock ){
        !           869:       AsyncLock *pLock = p->pLock;
        !           870:       AsyncFileLock *pIter;
        !           871:       assert(pLock && pLock->pList);
        !           872:       for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
        !           873:         if( pIter!=&p->lock && (
        !           874:           (eLock==SQLITE_LOCK_EXCLUSIVE && pIter->eLock>=SQLITE_LOCK_SHARED) ||
        !           875:           (eLock==SQLITE_LOCK_PENDING && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
        !           876:           (eLock==SQLITE_LOCK_RESERVED && pIter->eLock>=SQLITE_LOCK_RESERVED) ||
        !           877:           (eLock==SQLITE_LOCK_SHARED && pIter->eLock>=SQLITE_LOCK_PENDING)
        !           878:         )){
        !           879:           rc = SQLITE_BUSY;
        !           880:         }
        !           881:       }
        !           882:       if( rc==SQLITE_OK ){
        !           883:         p->lock.eLock = eLock;
        !           884:         p->lock.eAsyncLock = MAX(p->lock.eAsyncLock, eLock);
        !           885:       }
        !           886:       assert(p->lock.eAsyncLock>=p->lock.eLock);
        !           887:       if( rc==SQLITE_OK ){
        !           888:         rc = getFileLock(pLock);
        !           889:       }
        !           890:     }
        !           891:     async_mutex_leave(ASYNC_MUTEX_LOCK);
        !           892:   }
        !           893: 
        !           894:   ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc));
        !           895:   return rc;
        !           896: }
        !           897: static int asyncUnlock(sqlite3_file *pFile, int eLock){
        !           898:   int rc = SQLITE_OK;
        !           899:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           900:   if( p->zName ){
        !           901:     AsyncFileLock *pLock = &p->lock;
        !           902:     async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !           903:     async_mutex_enter(ASYNC_MUTEX_LOCK);
        !           904:     pLock->eLock = MIN(pLock->eLock, eLock);
        !           905:     rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
        !           906:     async_mutex_leave(ASYNC_MUTEX_LOCK);
        !           907:     async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !           908:   }
        !           909:   return rc;
        !           910: }
        !           911: 
        !           912: /*
        !           913: ** This function is called when the pager layer first opens a database file
        !           914: ** and is checking for a hot-journal.
        !           915: */
        !           916: static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
        !           917:   int ret = 0;
        !           918:   AsyncFileLock *pIter;
        !           919:   AsyncFileData *p = ((AsyncFile *)pFile)->pData;
        !           920: 
        !           921:   async_mutex_enter(ASYNC_MUTEX_LOCK);
        !           922:   for(pIter=p->pLock->pList; pIter; pIter=pIter->pNext){
        !           923:     if( pIter->eLock>=SQLITE_LOCK_RESERVED ){
        !           924:       ret = 1;
        !           925:       break;
        !           926:     }
        !           927:   }
        !           928:   async_mutex_leave(ASYNC_MUTEX_LOCK);
        !           929: 
        !           930:   ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", ret, p->zName));
        !           931:   *pResOut = ret;
        !           932:   return SQLITE_OK;
        !           933: }
        !           934: 
        !           935: /* 
        !           936: ** sqlite3_file_control() implementation.
        !           937: */
        !           938: static int asyncFileControl(sqlite3_file *id, int op, void *pArg){
        !           939:   switch( op ){
        !           940:     case SQLITE_FCNTL_LOCKSTATE: {
        !           941:       async_mutex_enter(ASYNC_MUTEX_LOCK);
        !           942:       *(int*)pArg = ((AsyncFile*)id)->pData->lock.eLock;
        !           943:       async_mutex_leave(ASYNC_MUTEX_LOCK);
        !           944:       return SQLITE_OK;
        !           945:     }
        !           946:   }
        !           947:   return SQLITE_ERROR;
        !           948: }
        !           949: 
        !           950: /* 
        !           951: ** Return the device characteristics and sector-size of the device. It
        !           952: ** is tricky to implement these correctly, as this backend might 
        !           953: ** not have an open file handle at this point.
        !           954: */
        !           955: static int asyncSectorSize(sqlite3_file *pFile){
        !           956:   UNUSED_PARAMETER(pFile);
        !           957:   return 512;
        !           958: }
        !           959: static int asyncDeviceCharacteristics(sqlite3_file *pFile){
        !           960:   UNUSED_PARAMETER(pFile);
        !           961:   return 0;
        !           962: }
        !           963: 
        !           964: static int unlinkAsyncFile(AsyncFileData *pData){
        !           965:   AsyncFileLock **ppIter;
        !           966:   int rc = SQLITE_OK;
        !           967: 
        !           968:   if( pData->zName ){
        !           969:     AsyncLock *pLock = pData->pLock;
        !           970:     for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){
        !           971:       if( (*ppIter)==&pData->lock ){
        !           972:         *ppIter = pData->lock.pNext;
        !           973:         break;
        !           974:       }
        !           975:     }
        !           976:     if( !pLock->pList ){
        !           977:       AsyncLock **pp;
        !           978:       if( pLock->pFile ){
        !           979:         pLock->pFile->pMethods->xClose(pLock->pFile);
        !           980:       }
        !           981:       for(pp=&async.pLock; *pp!=pLock; pp=&((*pp)->pNext));
        !           982:       *pp = pLock->pNext;
        !           983:       sqlite3_free(pLock);
        !           984:     }else{
        !           985:       rc = getFileLock(pLock);
        !           986:     }
        !           987:   }
        !           988: 
        !           989:   return rc;
        !           990: }
        !           991: 
        !           992: /*
        !           993: ** The parameter passed to this function is a copy of a 'flags' parameter
        !           994: ** passed to this modules xOpen() method. This function returns true
        !           995: ** if the file should be opened asynchronously, or false if it should
        !           996: ** be opened immediately.
        !           997: **
        !           998: ** If the file is to be opened asynchronously, then asyncOpen() will add
        !           999: ** an entry to the event queue and the file will not actually be opened
        !          1000: ** until the event is processed. Otherwise, the file is opened directly
        !          1001: ** by the caller.
        !          1002: */
        !          1003: static int doAsynchronousOpen(int flags){
        !          1004:   return (flags&SQLITE_OPEN_CREATE) && (
        !          1005:       (flags&SQLITE_OPEN_MAIN_JOURNAL) ||
        !          1006:       (flags&SQLITE_OPEN_TEMP_JOURNAL) ||
        !          1007:       (flags&SQLITE_OPEN_DELETEONCLOSE)
        !          1008:   );
        !          1009: }
        !          1010: 
        !          1011: /*
        !          1012: ** Open a file.
        !          1013: */
        !          1014: static int asyncOpen(
        !          1015:   sqlite3_vfs *pAsyncVfs,
        !          1016:   const char *zName,
        !          1017:   sqlite3_file *pFile,
        !          1018:   int flags,
        !          1019:   int *pOutFlags
        !          1020: ){
        !          1021:   static sqlite3_io_methods async_methods = {
        !          1022:     1,                               /* iVersion */
        !          1023:     asyncClose,                      /* xClose */
        !          1024:     asyncRead,                       /* xRead */
        !          1025:     asyncWrite,                      /* xWrite */
        !          1026:     asyncTruncate,                   /* xTruncate */
        !          1027:     asyncSync,                       /* xSync */
        !          1028:     asyncFileSize,                   /* xFileSize */
        !          1029:     asyncLock,                       /* xLock */
        !          1030:     asyncUnlock,                     /* xUnlock */
        !          1031:     asyncCheckReservedLock,          /* xCheckReservedLock */
        !          1032:     asyncFileControl,                /* xFileControl */
        !          1033:     asyncSectorSize,                 /* xSectorSize */
        !          1034:     asyncDeviceCharacteristics       /* xDeviceCharacteristics */
        !          1035:   };
        !          1036: 
        !          1037:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1038:   AsyncFile *p = (AsyncFile *)pFile;
        !          1039:   int nName = 0;
        !          1040:   int rc = SQLITE_OK;
        !          1041:   int nByte;
        !          1042:   AsyncFileData *pData;
        !          1043:   AsyncLock *pLock = 0;
        !          1044:   char *z;
        !          1045:   int isAsyncOpen = doAsynchronousOpen(flags);
        !          1046: 
        !          1047:   /* If zName is NULL, then the upper layer is requesting an anonymous file */
        !          1048:   if( zName ){
        !          1049:     nName = (int)strlen(zName)+1;
        !          1050:   }
        !          1051: 
        !          1052:   nByte = (
        !          1053:     sizeof(AsyncFileData) +        /* AsyncFileData structure */
        !          1054:     2 * pVfs->szOsFile +           /* AsyncFileData.pBaseRead and pBaseWrite */
        !          1055:     nName                          /* AsyncFileData.zName */
        !          1056:   ); 
        !          1057:   z = sqlite3_malloc(nByte);
        !          1058:   if( !z ){
        !          1059:     return SQLITE_NOMEM;
        !          1060:   }
        !          1061:   memset(z, 0, nByte);
        !          1062:   pData = (AsyncFileData*)z;
        !          1063:   z += sizeof(pData[0]);
        !          1064:   pData->pBaseRead = (sqlite3_file*)z;
        !          1065:   z += pVfs->szOsFile;
        !          1066:   pData->pBaseWrite = (sqlite3_file*)z;
        !          1067:   pData->closeOp.pFileData = pData;
        !          1068:   pData->closeOp.op = ASYNC_CLOSE;
        !          1069: 
        !          1070:   if( zName ){
        !          1071:     z += pVfs->szOsFile;
        !          1072:     pData->zName = z;
        !          1073:     pData->nName = nName;
        !          1074:     memcpy(pData->zName, zName, nName);
        !          1075:   }
        !          1076: 
        !          1077:   if( !isAsyncOpen ){
        !          1078:     int flagsout;
        !          1079:     rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, &flagsout);
        !          1080:     if( rc==SQLITE_OK 
        !          1081:      && (flagsout&SQLITE_OPEN_READWRITE) 
        !          1082:      && (flags&SQLITE_OPEN_EXCLUSIVE)==0
        !          1083:     ){
        !          1084:       rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseWrite, flags, 0);
        !          1085:     }
        !          1086:     if( pOutFlags ){
        !          1087:       *pOutFlags = flagsout;
        !          1088:     }
        !          1089:   }
        !          1090: 
        !          1091:   async_mutex_enter(ASYNC_MUTEX_LOCK);
        !          1092: 
        !          1093:   if( zName && rc==SQLITE_OK ){
        !          1094:     pLock = findLock(pData->zName, pData->nName);
        !          1095:     if( !pLock ){
        !          1096:       int nByte = pVfs->szOsFile + sizeof(AsyncLock) + pData->nName + 1; 
        !          1097:       pLock = (AsyncLock *)sqlite3_malloc(nByte);
        !          1098:       if( pLock ){
        !          1099:         memset(pLock, 0, nByte);
        !          1100:         if( async.bLockFiles && (flags&SQLITE_OPEN_MAIN_DB) ){
        !          1101:           pLock->pFile = (sqlite3_file *)&pLock[1];
        !          1102:           rc = pVfs->xOpen(pVfs, pData->zName, pLock->pFile, flags, 0);
        !          1103:           if( rc!=SQLITE_OK ){
        !          1104:             sqlite3_free(pLock);
        !          1105:             pLock = 0;
        !          1106:           }
        !          1107:         }
        !          1108:         if( pLock ){
        !          1109:           pLock->nFile = pData->nName;
        !          1110:           pLock->zFile = &((char *)(&pLock[1]))[pVfs->szOsFile];
        !          1111:           memcpy(pLock->zFile, pData->zName, pLock->nFile);
        !          1112:           pLock->pNext = async.pLock;
        !          1113:           async.pLock = pLock;
        !          1114:         }
        !          1115:       }else{
        !          1116:         rc = SQLITE_NOMEM;
        !          1117:       }
        !          1118:     }
        !          1119:   }
        !          1120: 
        !          1121:   if( rc==SQLITE_OK ){
        !          1122:     p->pMethod = &async_methods;
        !          1123:     p->pData = pData;
        !          1124: 
        !          1125:     /* Link AsyncFileData.lock into the linked list of 
        !          1126:     ** AsyncFileLock structures for this file.
        !          1127:     */
        !          1128:     if( zName ){
        !          1129:       pData->lock.pNext = pLock->pList;
        !          1130:       pLock->pList = &pData->lock;
        !          1131:       pData->zName = pLock->zFile;
        !          1132:     }
        !          1133:   }else{
        !          1134:     if( pData->pBaseRead->pMethods ){
        !          1135:       pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
        !          1136:     }
        !          1137:     if( pData->pBaseWrite->pMethods ){
        !          1138:       pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
        !          1139:     }
        !          1140:     sqlite3_free(pData);
        !          1141:   }
        !          1142: 
        !          1143:   async_mutex_leave(ASYNC_MUTEX_LOCK);
        !          1144: 
        !          1145:   if( rc==SQLITE_OK ){
        !          1146:     pData->pLock = pLock;
        !          1147:   }
        !          1148: 
        !          1149:   if( rc==SQLITE_OK && isAsyncOpen ){
        !          1150:     rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (sqlite3_int64)flags,0,0);
        !          1151:     if( rc==SQLITE_OK ){
        !          1152:       if( pOutFlags ) *pOutFlags = flags;
        !          1153:     }else{
        !          1154:       async_mutex_enter(ASYNC_MUTEX_LOCK);
        !          1155:       unlinkAsyncFile(pData);
        !          1156:       async_mutex_leave(ASYNC_MUTEX_LOCK);
        !          1157:       sqlite3_free(pData);
        !          1158:     }
        !          1159:   }
        !          1160:   if( rc!=SQLITE_OK ){
        !          1161:     p->pMethod = 0;
        !          1162:   }else{
        !          1163:     incrOpenFileCount();
        !          1164:   }
        !          1165: 
        !          1166:   return rc;
        !          1167: }
        !          1168: 
        !          1169: /*
        !          1170: ** Implementation of sqlite3OsDelete. Add an entry to the end of the 
        !          1171: ** write-op queue to perform the delete.
        !          1172: */
        !          1173: static int asyncDelete(sqlite3_vfs *pAsyncVfs, const char *z, int syncDir){
        !          1174:   UNUSED_PARAMETER(pAsyncVfs);
        !          1175:   return addNewAsyncWrite(0, ASYNC_DELETE, syncDir, (int)strlen(z)+1, z);
        !          1176: }
        !          1177: 
        !          1178: /*
        !          1179: ** Implementation of sqlite3OsAccess. This method holds the mutex from
        !          1180: ** start to finish.
        !          1181: */
        !          1182: static int asyncAccess(
        !          1183:   sqlite3_vfs *pAsyncVfs, 
        !          1184:   const char *zName, 
        !          1185:   int flags,
        !          1186:   int *pResOut
        !          1187: ){
        !          1188:   int rc;
        !          1189:   int ret;
        !          1190:   AsyncWrite *p;
        !          1191:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1192: 
        !          1193:   assert(flags==SQLITE_ACCESS_READWRITE 
        !          1194:       || flags==SQLITE_ACCESS_READ 
        !          1195:       || flags==SQLITE_ACCESS_EXISTS 
        !          1196:   );
        !          1197: 
        !          1198:   async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1199:   rc = pVfs->xAccess(pVfs, zName, flags, &ret);
        !          1200:   if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
        !          1201:     for(p=async.pQueueFirst; p; p = p->pNext){
        !          1202:       if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){
        !          1203:         ret = 0;
        !          1204:       }else if( p->op==ASYNC_OPENEXCLUSIVE 
        !          1205:              && p->pFileData->zName
        !          1206:              && 0==strcmp(p->pFileData->zName, zName) 
        !          1207:       ){
        !          1208:         ret = 1;
        !          1209:       }
        !          1210:     }
        !          1211:   }
        !          1212:   ASYNC_TRACE(("ACCESS(%s): %s = %d\n", 
        !          1213:     flags==SQLITE_ACCESS_READWRITE?"read-write":
        !          1214:     flags==SQLITE_ACCESS_READ?"read":"exists"
        !          1215:     , zName, ret)
        !          1216:   );
        !          1217:   async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1218:   *pResOut = ret;
        !          1219:   return rc;
        !          1220: }
        !          1221: 
        !          1222: /*
        !          1223: ** Fill in zPathOut with the full path to the file identified by zPath.
        !          1224: */
        !          1225: static int asyncFullPathname(
        !          1226:   sqlite3_vfs *pAsyncVfs, 
        !          1227:   const char *zPath, 
        !          1228:   int nPathOut,
        !          1229:   char *zPathOut
        !          1230: ){
        !          1231:   int rc;
        !          1232:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1233:   rc = pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
        !          1234: 
        !          1235:   /* Because of the way intra-process file locking works, this backend
        !          1236:   ** needs to return a canonical path. The following block assumes the
        !          1237:   ** file-system uses unix style paths. 
        !          1238:   */
        !          1239:   if( rc==SQLITE_OK ){
        !          1240:     int i, j;
        !          1241:     char *z = zPathOut;
        !          1242:     int n = (int)strlen(z);
        !          1243:     while( n>1 && z[n-1]=='/' ){ n--; }
        !          1244:     for(i=j=0; i<n; i++){
        !          1245:       if( z[i]=='/' ){
        !          1246:         if( z[i+1]=='/' ) continue;
        !          1247:         if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
        !          1248:           i += 1;
        !          1249:           continue;
        !          1250:         }
        !          1251:         if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
        !          1252:           while( j>0 && z[j-1]!='/' ){ j--; }
        !          1253:           if( j>0 ){ j--; }
        !          1254:           i += 2;
        !          1255:           continue;
        !          1256:         }
        !          1257:       }
        !          1258:       z[j++] = z[i];
        !          1259:     }
        !          1260:     z[j] = 0;
        !          1261:   }
        !          1262: 
        !          1263:   return rc;
        !          1264: }
        !          1265: static void *asyncDlOpen(sqlite3_vfs *pAsyncVfs, const char *zPath){
        !          1266:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1267:   return pVfs->xDlOpen(pVfs, zPath);
        !          1268: }
        !          1269: static void asyncDlError(sqlite3_vfs *pAsyncVfs, int nByte, char *zErrMsg){
        !          1270:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1271:   pVfs->xDlError(pVfs, nByte, zErrMsg);
        !          1272: }
        !          1273: static void (*asyncDlSym(
        !          1274:   sqlite3_vfs *pAsyncVfs, 
        !          1275:   void *pHandle, 
        !          1276:   const char *zSymbol
        !          1277: ))(void){
        !          1278:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1279:   return pVfs->xDlSym(pVfs, pHandle, zSymbol);
        !          1280: }
        !          1281: static void asyncDlClose(sqlite3_vfs *pAsyncVfs, void *pHandle){
        !          1282:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1283:   pVfs->xDlClose(pVfs, pHandle);
        !          1284: }
        !          1285: static int asyncRandomness(sqlite3_vfs *pAsyncVfs, int nByte, char *zBufOut){
        !          1286:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1287:   return pVfs->xRandomness(pVfs, nByte, zBufOut);
        !          1288: }
        !          1289: static int asyncSleep(sqlite3_vfs *pAsyncVfs, int nMicro){
        !          1290:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1291:   return pVfs->xSleep(pVfs, nMicro);
        !          1292: }
        !          1293: static int asyncCurrentTime(sqlite3_vfs *pAsyncVfs, double *pTimeOut){
        !          1294:   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
        !          1295:   return pVfs->xCurrentTime(pVfs, pTimeOut);
        !          1296: }
        !          1297: 
        !          1298: static sqlite3_vfs async_vfs = {
        !          1299:   1,                    /* iVersion */
        !          1300:   sizeof(AsyncFile),    /* szOsFile */
        !          1301:   0,                    /* mxPathname */
        !          1302:   0,                    /* pNext */
        !          1303:   SQLITEASYNC_VFSNAME,  /* zName */
        !          1304:   0,                    /* pAppData */
        !          1305:   asyncOpen,            /* xOpen */
        !          1306:   asyncDelete,          /* xDelete */
        !          1307:   asyncAccess,          /* xAccess */
        !          1308:   asyncFullPathname,    /* xFullPathname */
        !          1309:   asyncDlOpen,          /* xDlOpen */
        !          1310:   asyncDlError,         /* xDlError */
        !          1311:   asyncDlSym,           /* xDlSym */
        !          1312:   asyncDlClose,         /* xDlClose */
        !          1313:   asyncRandomness,      /* xDlError */
        !          1314:   asyncSleep,           /* xDlSym */
        !          1315:   asyncCurrentTime      /* xDlClose */
        !          1316: };
        !          1317: 
        !          1318: /* 
        !          1319: ** This procedure runs in a separate thread, reading messages off of the
        !          1320: ** write queue and processing them one by one.  
        !          1321: **
        !          1322: ** If async.writerHaltNow is true, then this procedure exits
        !          1323: ** after processing a single message.
        !          1324: **
        !          1325: ** If async.writerHaltWhenIdle is true, then this procedure exits when
        !          1326: ** the write queue is empty.
        !          1327: **
        !          1328: ** If both of the above variables are false, this procedure runs
        !          1329: ** indefinately, waiting for operations to be added to the write queue
        !          1330: ** and processing them in the order in which they arrive.
        !          1331: **
        !          1332: ** An artifical delay of async.ioDelay milliseconds is inserted before
        !          1333: ** each write operation in order to simulate the effect of a slow disk.
        !          1334: **
        !          1335: ** Only one instance of this procedure may be running at a time.
        !          1336: */
        !          1337: static void asyncWriterThread(void){
        !          1338:   sqlite3_vfs *pVfs = (sqlite3_vfs *)(async_vfs.pAppData);
        !          1339:   AsyncWrite *p = 0;
        !          1340:   int rc = SQLITE_OK;
        !          1341:   int holdingMutex = 0;
        !          1342: 
        !          1343:   async_mutex_enter(ASYNC_MUTEX_WRITER);
        !          1344: 
        !          1345:   while( async.eHalt!=SQLITEASYNC_HALT_NOW ){
        !          1346:     int doNotFree = 0;
        !          1347:     sqlite3_file *pBase = 0;
        !          1348: 
        !          1349:     if( !holdingMutex ){
        !          1350:       async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1351:     }
        !          1352:     while( (p = async.pQueueFirst)==0 ){
        !          1353:       if( async.eHalt!=SQLITEASYNC_HALT_NEVER ){
        !          1354:         async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1355:         break;
        !          1356:       }else{
        !          1357:         ASYNC_TRACE(("IDLE\n"));
        !          1358:         async_cond_wait(ASYNC_COND_QUEUE, ASYNC_MUTEX_QUEUE);
        !          1359:         ASYNC_TRACE(("WAKEUP\n"));
        !          1360:       }
        !          1361:     }
        !          1362:     if( p==0 ) break;
        !          1363:     holdingMutex = 1;
        !          1364: 
        !          1365:     /* Right now this thread is holding the mutex on the write-op queue.
        !          1366:     ** Variable 'p' points to the first entry in the write-op queue. In
        !          1367:     ** the general case, we hold on to the mutex for the entire body of
        !          1368:     ** the loop. 
        !          1369:     **
        !          1370:     ** However in the cases enumerated below, we relinquish the mutex,
        !          1371:     ** perform the IO, and then re-request the mutex before removing 'p' from
        !          1372:     ** the head of the write-op queue. The idea is to increase concurrency with
        !          1373:     ** sqlite threads.
        !          1374:     **
        !          1375:     **     * An ASYNC_CLOSE operation.
        !          1376:     **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish 
        !          1377:     **       the mutex, call the underlying xOpenExclusive() function, then
        !          1378:     **       re-aquire the mutex before seting the AsyncFile.pBaseRead 
        !          1379:     **       variable.
        !          1380:     **     * ASYNC_SYNC and ASYNC_WRITE operations, if 
        !          1381:     **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two
        !          1382:     **       file-handles are open for the particular file being "synced".
        !          1383:     */
        !          1384:     if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){
        !          1385:       p->op = ASYNC_NOOP;
        !          1386:     }
        !          1387:     if( p->pFileData ){
        !          1388:       pBase = p->pFileData->pBaseWrite;
        !          1389:       if( 
        !          1390:         p->op==ASYNC_CLOSE || 
        !          1391:         p->op==ASYNC_OPENEXCLUSIVE ||
        !          1392:         (pBase->pMethods && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) ) 
        !          1393:       ){
        !          1394:         async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1395:         holdingMutex = 0;
        !          1396:       }
        !          1397:       if( !pBase->pMethods ){
        !          1398:         pBase = p->pFileData->pBaseRead;
        !          1399:       }
        !          1400:     }
        !          1401: 
        !          1402:     switch( p->op ){
        !          1403:       case ASYNC_NOOP:
        !          1404:         break;
        !          1405: 
        !          1406:       case ASYNC_WRITE:
        !          1407:         assert( pBase );
        !          1408:         ASYNC_TRACE(("WRITE %s %d bytes at %d\n",
        !          1409:                 p->pFileData->zName, p->nByte, p->iOffset));
        !          1410:         rc = pBase->pMethods->xWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset);
        !          1411:         break;
        !          1412: 
        !          1413:       case ASYNC_SYNC:
        !          1414:         assert( pBase );
        !          1415:         ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName));
        !          1416:         rc = pBase->pMethods->xSync(pBase, p->nByte);
        !          1417:         break;
        !          1418: 
        !          1419:       case ASYNC_TRUNCATE:
        !          1420:         assert( pBase );
        !          1421:         ASYNC_TRACE(("TRUNCATE %s to %d bytes\n", 
        !          1422:                 p->pFileData->zName, p->iOffset));
        !          1423:         rc = pBase->pMethods->xTruncate(pBase, p->iOffset);
        !          1424:         break;
        !          1425: 
        !          1426:       case ASYNC_CLOSE: {
        !          1427:         AsyncFileData *pData = p->pFileData;
        !          1428:         ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName));
        !          1429:         if( pData->pBaseWrite->pMethods ){
        !          1430:           pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
        !          1431:         }
        !          1432:         if( pData->pBaseRead->pMethods ){
        !          1433:           pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
        !          1434:         }
        !          1435: 
        !          1436:         /* Unlink AsyncFileData.lock from the linked list of AsyncFileLock 
        !          1437:         ** structures for this file. Obtain the async.lockMutex mutex 
        !          1438:         ** before doing so.
        !          1439:         */
        !          1440:         async_mutex_enter(ASYNC_MUTEX_LOCK);
        !          1441:         rc = unlinkAsyncFile(pData);
        !          1442:         async_mutex_leave(ASYNC_MUTEX_LOCK);
        !          1443: 
        !          1444:         if( !holdingMutex ){
        !          1445:           async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1446:           holdingMutex = 1;
        !          1447:         }
        !          1448:         assert_mutex_is_held(ASYNC_MUTEX_QUEUE);
        !          1449:         async.pQueueFirst = p->pNext;
        !          1450:         sqlite3_free(pData);
        !          1451:         doNotFree = 1;
        !          1452:         break;
        !          1453:       }
        !          1454: 
        !          1455:       case ASYNC_UNLOCK: {
        !          1456:         AsyncWrite *pIter;
        !          1457:         AsyncFileData *pData = p->pFileData;
        !          1458:         int eLock = p->nByte;
        !          1459: 
        !          1460:         /* When a file is locked by SQLite using the async backend, it is 
        !          1461:         ** locked within the 'real' file-system synchronously. When it is
        !          1462:         ** unlocked, an ASYNC_UNLOCK event is added to the write-queue to
        !          1463:         ** unlock the file asynchronously. The design of the async backend
        !          1464:         ** requires that the 'real' file-system file be locked from the
        !          1465:         ** time that SQLite first locks it (and probably reads from it)
        !          1466:         ** until all asynchronous write events that were scheduled before
        !          1467:         ** SQLite unlocked the file have been processed.
        !          1468:         **
        !          1469:         ** This is more complex if SQLite locks and unlocks the file multiple
        !          1470:         ** times in quick succession. For example, if SQLite does: 
        !          1471:         ** 
        !          1472:         **   lock, write, unlock, lock, write, unlock
        !          1473:         **
        !          1474:         ** Each "lock" operation locks the file immediately. Each "write" 
        !          1475:         ** and "unlock" operation adds an event to the event queue. If the
        !          1476:         ** second "lock" operation is performed before the first "unlock"
        !          1477:         ** operation has been processed asynchronously, then the first
        !          1478:         ** "unlock" cannot be safely processed as is, since this would mean
        !          1479:         ** the file was unlocked when the second "write" operation is
        !          1480:         ** processed. To work around this, when processing an ASYNC_UNLOCK
        !          1481:         ** operation, SQLite:
        !          1482:         **
        !          1483:         **   1) Unlocks the file to the minimum of the argument passed to
        !          1484:         **      the xUnlock() call and the current lock from SQLite's point
        !          1485:         **      of view, and
        !          1486:         **
        !          1487:         **   2) Only unlocks the file at all if this event is the last
        !          1488:         **      ASYNC_UNLOCK event on this file in the write-queue.
        !          1489:         */ 
        !          1490:         assert( holdingMutex==1 );
        !          1491:         assert( async.pQueueFirst==p );
        !          1492:         for(pIter=async.pQueueFirst->pNext; pIter; pIter=pIter->pNext){
        !          1493:           if( pIter->pFileData==pData && pIter->op==ASYNC_UNLOCK ) break;
        !          1494:         }
        !          1495:         if( !pIter ){
        !          1496:           async_mutex_enter(ASYNC_MUTEX_LOCK);
        !          1497:           pData->lock.eAsyncLock = MIN(
        !          1498:               pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
        !          1499:           );
        !          1500:           assert(pData->lock.eAsyncLock>=pData->lock.eLock);
        !          1501:           rc = getFileLock(pData->pLock);
        !          1502:           async_mutex_leave(ASYNC_MUTEX_LOCK);
        !          1503:         }
        !          1504:         break;
        !          1505:       }
        !          1506: 
        !          1507:       case ASYNC_DELETE:
        !          1508:         ASYNC_TRACE(("DELETE %s\n", p->zBuf));
        !          1509:         rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset);
        !          1510:         break;
        !          1511: 
        !          1512:       case ASYNC_OPENEXCLUSIVE: {
        !          1513:         int flags = (int)p->iOffset;
        !          1514:         AsyncFileData *pData = p->pFileData;
        !          1515:         ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset));
        !          1516:         assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0);
        !          1517:         rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0);
        !          1518:         assert( holdingMutex==0 );
        !          1519:         async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1520:         holdingMutex = 1;
        !          1521:         break;
        !          1522:       }
        !          1523: 
        !          1524:       default: assert(!"Illegal value for AsyncWrite.op");
        !          1525:     }
        !          1526: 
        !          1527:     /* If we didn't hang on to the mutex during the IO op, obtain it now
        !          1528:     ** so that the AsyncWrite structure can be safely removed from the 
        !          1529:     ** global write-op queue.
        !          1530:     */
        !          1531:     if( !holdingMutex ){
        !          1532:       async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1533:       holdingMutex = 1;
        !          1534:     }
        !          1535:     /* ASYNC_TRACE(("UNLINK %p\n", p)); */
        !          1536:     if( p==async.pQueueLast ){
        !          1537:       async.pQueueLast = 0;
        !          1538:     }
        !          1539:     if( !doNotFree ){
        !          1540:       assert_mutex_is_held(ASYNC_MUTEX_QUEUE);
        !          1541:       async.pQueueFirst = p->pNext;
        !          1542:       sqlite3_free(p);
        !          1543:     }
        !          1544:     assert( holdingMutex );
        !          1545: 
        !          1546:     /* An IO error has occurred. We cannot report the error back to the
        !          1547:     ** connection that requested the I/O since the error happened 
        !          1548:     ** asynchronously.  The connection has already moved on.  There 
        !          1549:     ** really is nobody to report the error to.
        !          1550:     **
        !          1551:     ** The file for which the error occurred may have been a database or
        !          1552:     ** journal file. Regardless, none of the currently queued operations
        !          1553:     ** associated with the same database should now be performed. Nor should
        !          1554:     ** any subsequently requested IO on either a database or journal file 
        !          1555:     ** handle for the same database be accepted until the main database
        !          1556:     ** file handle has been closed and reopened.
        !          1557:     **
        !          1558:     ** Furthermore, no further IO should be queued or performed on any file
        !          1559:     ** handle associated with a database that may have been part of a 
        !          1560:     ** multi-file transaction that included the database associated with 
        !          1561:     ** the IO error (i.e. a database ATTACHed to the same handle at some 
        !          1562:     ** point in time).
        !          1563:     */
        !          1564:     if( rc!=SQLITE_OK ){
        !          1565:       async.ioError = rc;
        !          1566:     }
        !          1567: 
        !          1568:     if( async.ioError && !async.pQueueFirst ){
        !          1569:       async_mutex_enter(ASYNC_MUTEX_LOCK);
        !          1570:       if( 0==async.pLock ){
        !          1571:         async.ioError = SQLITE_OK;
        !          1572:       }
        !          1573:       async_mutex_leave(ASYNC_MUTEX_LOCK);
        !          1574:     }
        !          1575: 
        !          1576:     /* Drop the queue mutex before continuing to the next write operation
        !          1577:     ** in order to give other threads a chance to work with the write queue.
        !          1578:     */
        !          1579:     if( !async.pQueueFirst || !async.ioError ){
        !          1580:       async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1581:       holdingMutex = 0;
        !          1582:       if( async.ioDelay>0 ){
        !          1583:         pVfs->xSleep(pVfs, async.ioDelay*1000);
        !          1584:       }else{
        !          1585:         async_sched_yield();
        !          1586:       }
        !          1587:     }
        !          1588:   }
        !          1589:   
        !          1590:   async_mutex_leave(ASYNC_MUTEX_WRITER);
        !          1591:   return;
        !          1592: }
        !          1593: 
        !          1594: /*
        !          1595: ** Install the asynchronous VFS.
        !          1596: */ 
        !          1597: int sqlite3async_initialize(const char *zParent, int isDefault){
        !          1598:   int rc = SQLITE_OK;
        !          1599:   if( async_vfs.pAppData==0 ){
        !          1600:     sqlite3_vfs *pParent = sqlite3_vfs_find(zParent);
        !          1601:     if( !pParent || async_os_initialize() ){
        !          1602:       rc = SQLITE_ERROR;
        !          1603:     }else if( SQLITE_OK!=(rc = sqlite3_vfs_register(&async_vfs, isDefault)) ){
        !          1604:       async_os_shutdown();
        !          1605:     }else{
        !          1606:       async_vfs.pAppData = (void *)pParent;
        !          1607:       async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname;
        !          1608:     }
        !          1609:   }
        !          1610:   return rc;
        !          1611: }
        !          1612: 
        !          1613: /*
        !          1614: ** Uninstall the asynchronous VFS.
        !          1615: */
        !          1616: void sqlite3async_shutdown(void){
        !          1617:   if( async_vfs.pAppData ){
        !          1618:     async_os_shutdown();
        !          1619:     sqlite3_vfs_unregister((sqlite3_vfs *)&async_vfs);
        !          1620:     async_vfs.pAppData = 0;
        !          1621:   }
        !          1622: }
        !          1623: 
        !          1624: /*
        !          1625: ** Process events on the write-queue.
        !          1626: */
        !          1627: void sqlite3async_run(void){
        !          1628:   asyncWriterThread();
        !          1629: }
        !          1630: 
        !          1631: /*
        !          1632: ** Control/configure the asynchronous IO system.
        !          1633: */
        !          1634: int sqlite3async_control(int op, ...){
        !          1635:   va_list ap;
        !          1636:   va_start(ap, op);
        !          1637:   switch( op ){
        !          1638:     case SQLITEASYNC_HALT: {
        !          1639:       int eWhen = va_arg(ap, int);
        !          1640:       if( eWhen!=SQLITEASYNC_HALT_NEVER
        !          1641:        && eWhen!=SQLITEASYNC_HALT_NOW
        !          1642:        && eWhen!=SQLITEASYNC_HALT_IDLE
        !          1643:       ){
        !          1644:         return SQLITE_MISUSE;
        !          1645:       }
        !          1646:       async.eHalt = eWhen;
        !          1647:       async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1648:       async_cond_signal(ASYNC_COND_QUEUE);
        !          1649:       async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1650:       break;
        !          1651:     }
        !          1652: 
        !          1653:     case SQLITEASYNC_DELAY: {
        !          1654:       int iDelay = va_arg(ap, int);
        !          1655:       if( iDelay<0 ){
        !          1656:         return SQLITE_MISUSE;
        !          1657:       }
        !          1658:       async.ioDelay = iDelay;
        !          1659:       break;
        !          1660:     }
        !          1661: 
        !          1662:     case SQLITEASYNC_LOCKFILES: {
        !          1663:       int bLock = va_arg(ap, int);
        !          1664:       async_mutex_enter(ASYNC_MUTEX_QUEUE);
        !          1665:       if( async.nFile || async.pQueueFirst ){
        !          1666:         async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1667:         return SQLITE_MISUSE;
        !          1668:       }
        !          1669:       async.bLockFiles = bLock;
        !          1670:       async_mutex_leave(ASYNC_MUTEX_QUEUE);
        !          1671:       break;
        !          1672:     }
        !          1673:       
        !          1674:     case SQLITEASYNC_GET_HALT: {
        !          1675:       int *peWhen = va_arg(ap, int *);
        !          1676:       *peWhen = async.eHalt;
        !          1677:       break;
        !          1678:     }
        !          1679:     case SQLITEASYNC_GET_DELAY: {
        !          1680:       int *piDelay = va_arg(ap, int *);
        !          1681:       *piDelay = async.ioDelay;
        !          1682:       break;
        !          1683:     }
        !          1684:     case SQLITEASYNC_GET_LOCKFILES: {
        !          1685:       int *piDelay = va_arg(ap, int *);
        !          1686:       *piDelay = async.bLockFiles;
        !          1687:       break;
        !          1688:     }
        !          1689: 
        !          1690:     default:
        !          1691:       return SQLITE_ERROR;
        !          1692:   }
        !          1693:   return SQLITE_OK;
        !          1694: }
        !          1695: 
        !          1696: #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */
        !          1697: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>