| OLD | NEW | 
 | (Empty) | 
|     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; |  | 
|   671   int nRead; |  | 
|   672   sqlite3_file *pBase = p->pBaseRead; |  | 
|   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     rc = pBase->pMethods->xFileSize(pBase, &filesize); |  | 
|   687     if( rc!=SQLITE_OK ){ |  | 
|   688       goto asyncread_out; |  | 
|   689     } |  | 
|   690     nRead = (int)MIN(filesize - iOffset, iAmt); |  | 
|   691     if( nRead>0 ){ |  | 
|   692       rc = pBase->pMethods->xRead(pBase, zOut, nRead, iOffset); |  | 
|   693       ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset)); |  | 
|   694     } |  | 
|   695   } |  | 
|   696  |  | 
|   697   if( rc==SQLITE_OK ){ |  | 
|   698     AsyncWrite *pWrite; |  | 
|   699     char *zName = p->zName; |  | 
|   700  |  | 
|   701     for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){ |  | 
|   702       if( pWrite->op==ASYNC_WRITE && ( |  | 
|   703         (pWrite->pFileData==p) || |  | 
|   704         (zName && pWrite->pFileData->zName==zName) |  | 
|   705       )){ |  | 
|   706         sqlite3_int64 iBeginOut = (pWrite->iOffset-iOffset); |  | 
|   707         sqlite3_int64 iBeginIn = -iBeginOut; |  | 
|   708         int nCopy; |  | 
|   709  |  | 
|   710         if( iBeginIn<0 ) iBeginIn = 0; |  | 
|   711         if( iBeginOut<0 ) iBeginOut = 0; |  | 
|   712         nCopy = (int)MIN(pWrite->nByte-iBeginIn, iAmt-iBeginOut); |  | 
|   713  |  | 
|   714         if( nCopy>0 ){ |  | 
|   715           memcpy(&((char *)zOut)[iBeginOut], &pWrite->zBuf[iBeginIn], nCopy); |  | 
|   716           ASYNC_TRACE(("OVERREAD %d bytes at %d\n", nCopy, iBeginOut+iOffset)); |  | 
|   717         } |  | 
|   718       } |  | 
|   719     } |  | 
|   720   } |  | 
|   721  |  | 
|   722 asyncread_out: |  | 
|   723   async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|   724   return rc; |  | 
|   725 } |  | 
|   726  |  | 
|   727 /* |  | 
|   728 ** Truncate the file to nByte bytes in length. This just adds an entry to  |  | 
|   729 ** the write-op list, no IO actually takes place. |  | 
|   730 */ |  | 
|   731 static int asyncTruncate(sqlite3_file *pFile, sqlite3_int64 nByte){ |  | 
|   732   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   733   return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0); |  | 
|   734 } |  | 
|   735  |  | 
|   736 /* |  | 
|   737 ** Sync the file. This just adds an entry to the write-op list, the  |  | 
|   738 ** sync() is done later by sqlite3_async_flush(). |  | 
|   739 */ |  | 
|   740 static int asyncSync(sqlite3_file *pFile, int flags){ |  | 
|   741   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   742   return addNewAsyncWrite(p, ASYNC_SYNC, 0, flags, 0); |  | 
|   743 } |  | 
|   744  |  | 
|   745 /* |  | 
|   746 ** Read the size of the file. First we read the size of the file system  |  | 
|   747 ** entry, then adjust for any ASYNC_WRITE or ASYNC_TRUNCATE operations  |  | 
|   748 ** currently in the write-op list.  |  | 
|   749 ** |  | 
|   750 ** This method holds the mutex from start to finish. |  | 
|   751 */ |  | 
|   752 int asyncFileSize(sqlite3_file *pFile, sqlite3_int64 *piSize){ |  | 
|   753   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   754   int rc = SQLITE_OK; |  | 
|   755   sqlite3_int64 s = 0; |  | 
|   756   sqlite3_file *pBase; |  | 
|   757  |  | 
|   758   async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|   759  |  | 
|   760   /* Read the filesystem size from the base file. If pMethods is NULL, this |  | 
|   761   ** means the file hasn't been opened yet. In this case all relevant data  |  | 
|   762   ** must be in the write-op queue anyway, so we can omit reading from the |  | 
|   763   ** file-system. |  | 
|   764   */ |  | 
|   765   pBase = p->pBaseRead; |  | 
|   766   if( pBase->pMethods ){ |  | 
|   767     rc = pBase->pMethods->xFileSize(pBase, &s); |  | 
|   768   } |  | 
|   769  |  | 
|   770   if( rc==SQLITE_OK ){ |  | 
|   771     AsyncWrite *pWrite; |  | 
|   772     for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){ |  | 
|   773       if( pWrite->op==ASYNC_DELETE  |  | 
|   774        && p->zName  |  | 
|   775        && strcmp(p->zName, pWrite->zBuf)==0  |  | 
|   776       ){ |  | 
|   777         s = 0; |  | 
|   778       }else if( pWrite->pFileData && ( |  | 
|   779           (pWrite->pFileData==p)  |  | 
|   780        || (p->zName && pWrite->pFileData->zName==p->zName)  |  | 
|   781       )){ |  | 
|   782         switch( pWrite->op ){ |  | 
|   783           case ASYNC_WRITE: |  | 
|   784             s = MAX(pWrite->iOffset + (sqlite3_int64)(pWrite->nByte), s); |  | 
|   785             break; |  | 
|   786           case ASYNC_TRUNCATE: |  | 
|   787             s = MIN(s, pWrite->iOffset); |  | 
|   788             break; |  | 
|   789         } |  | 
|   790       } |  | 
|   791     } |  | 
|   792     *piSize = s; |  | 
|   793   } |  | 
|   794   async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|   795   return rc; |  | 
|   796 } |  | 
|   797  |  | 
|   798 /* |  | 
|   799 ** Lock or unlock the actual file-system entry. |  | 
|   800 */ |  | 
|   801 static int getFileLock(AsyncLock *pLock){ |  | 
|   802   int rc = SQLITE_OK; |  | 
|   803   AsyncFileLock *pIter; |  | 
|   804   int eRequired = 0; |  | 
|   805  |  | 
|   806   if( pLock->pFile ){ |  | 
|   807     for(pIter=pLock->pList; pIter; pIter=pIter->pNext){ |  | 
|   808       assert(pIter->eAsyncLock>=pIter->eLock); |  | 
|   809       if( pIter->eAsyncLock>eRequired ){ |  | 
|   810         eRequired = pIter->eAsyncLock; |  | 
|   811         assert(eRequired>=0 && eRequired<=SQLITE_LOCK_EXCLUSIVE); |  | 
|   812       } |  | 
|   813     } |  | 
|   814  |  | 
|   815     if( eRequired>pLock->eLock ){ |  | 
|   816       rc = pLock->pFile->pMethods->xLock(pLock->pFile, eRequired); |  | 
|   817       if( rc==SQLITE_OK ){ |  | 
|   818         pLock->eLock = eRequired; |  | 
|   819       } |  | 
|   820     } |  | 
|   821     else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){ |  | 
|   822       rc = pLock->pFile->pMethods->xUnlock(pLock->pFile, eRequired); |  | 
|   823       if( rc==SQLITE_OK ){ |  | 
|   824         pLock->eLock = eRequired; |  | 
|   825       } |  | 
|   826     } |  | 
|   827   } |  | 
|   828  |  | 
|   829   return rc; |  | 
|   830 } |  | 
|   831  |  | 
|   832 /* |  | 
|   833 ** Return the AsyncLock structure from the global async.pLock list  |  | 
|   834 ** associated with the file-system entry identified by path zName  |  | 
|   835 ** (a string of nName bytes). If no such structure exists, return 0. |  | 
|   836 */ |  | 
|   837 static AsyncLock *findLock(const char *zName, int nName){ |  | 
|   838   AsyncLock *p = async.pLock; |  | 
|   839   while( p && (p->nFile!=nName || memcmp(p->zFile, zName, nName)) ){ |  | 
|   840     p = p->pNext; |  | 
|   841   } |  | 
|   842   return p; |  | 
|   843 } |  | 
|   844  |  | 
|   845 /* |  | 
|   846 ** The following two methods - asyncLock() and asyncUnlock() - are used |  | 
|   847 ** to obtain and release locks on database files opened with the |  | 
|   848 ** asynchronous backend. |  | 
|   849 */ |  | 
|   850 static int asyncLock(sqlite3_file *pFile, int eLock){ |  | 
|   851   int rc = SQLITE_OK; |  | 
|   852   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   853  |  | 
|   854   if( p->zName ){ |  | 
|   855     async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|   856     if( p->lock.eLock<eLock ){ |  | 
|   857       AsyncLock *pLock = p->pLock; |  | 
|   858       AsyncFileLock *pIter; |  | 
|   859       assert(pLock && pLock->pList); |  | 
|   860       for(pIter=pLock->pList; pIter; pIter=pIter->pNext){ |  | 
|   861         if( pIter!=&p->lock && ( |  | 
|   862           (eLock==SQLITE_LOCK_EXCLUSIVE && pIter->eLock>=SQLITE_LOCK_SHARED) || |  | 
|   863           (eLock==SQLITE_LOCK_PENDING && pIter->eLock>=SQLITE_LOCK_RESERVED) || |  | 
|   864           (eLock==SQLITE_LOCK_RESERVED && pIter->eLock>=SQLITE_LOCK_RESERVED) || |  | 
|   865           (eLock==SQLITE_LOCK_SHARED && pIter->eLock>=SQLITE_LOCK_PENDING) |  | 
|   866         )){ |  | 
|   867           rc = SQLITE_BUSY; |  | 
|   868         } |  | 
|   869       } |  | 
|   870       if( rc==SQLITE_OK ){ |  | 
|   871         p->lock.eLock = eLock; |  | 
|   872         p->lock.eAsyncLock = MAX(p->lock.eAsyncLock, eLock); |  | 
|   873       } |  | 
|   874       assert(p->lock.eAsyncLock>=p->lock.eLock); |  | 
|   875       if( rc==SQLITE_OK ){ |  | 
|   876         rc = getFileLock(pLock); |  | 
|   877       } |  | 
|   878     } |  | 
|   879     async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|   880   } |  | 
|   881  |  | 
|   882   ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc)); |  | 
|   883   return rc; |  | 
|   884 } |  | 
|   885 static int asyncUnlock(sqlite3_file *pFile, int eLock){ |  | 
|   886   int rc = SQLITE_OK; |  | 
|   887   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   888   if( p->zName ){ |  | 
|   889     AsyncFileLock *pLock = &p->lock; |  | 
|   890     async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|   891     async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|   892     pLock->eLock = MIN(pLock->eLock, eLock); |  | 
|   893     rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0); |  | 
|   894     async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|   895     async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|   896   } |  | 
|   897   return rc; |  | 
|   898 } |  | 
|   899  |  | 
|   900 /* |  | 
|   901 ** This function is called when the pager layer first opens a database file |  | 
|   902 ** and is checking for a hot-journal. |  | 
|   903 */ |  | 
|   904 static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){ |  | 
|   905   int ret = 0; |  | 
|   906   AsyncFileLock *pIter; |  | 
|   907   AsyncFileData *p = ((AsyncFile *)pFile)->pData; |  | 
|   908  |  | 
|   909   async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|   910   for(pIter=p->pLock->pList; pIter; pIter=pIter->pNext){ |  | 
|   911     if( pIter->eLock>=SQLITE_LOCK_RESERVED ){ |  | 
|   912       ret = 1; |  | 
|   913       break; |  | 
|   914     } |  | 
|   915   } |  | 
|   916   async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|   917  |  | 
|   918   ASYNC_TRACE(("CHECK-LOCK %d (%s)\n", ret, p->zName)); |  | 
|   919   *pResOut = ret; |  | 
|   920   return SQLITE_OK; |  | 
|   921 } |  | 
|   922  |  | 
|   923 /*  |  | 
|   924 ** sqlite3_file_control() implementation. |  | 
|   925 */ |  | 
|   926 static int asyncFileControl(sqlite3_file *id, int op, void *pArg){ |  | 
|   927   switch( op ){ |  | 
|   928     case SQLITE_FCNTL_LOCKSTATE: { |  | 
|   929       async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|   930       *(int*)pArg = ((AsyncFile*)id)->pData->lock.eLock; |  | 
|   931       async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|   932       return SQLITE_OK; |  | 
|   933     } |  | 
|   934   } |  | 
|   935   return SQLITE_ERROR; |  | 
|   936 } |  | 
|   937  |  | 
|   938 /*  |  | 
|   939 ** Return the device characteristics and sector-size of the device. It |  | 
|   940 ** is tricky to implement these correctly, as this backend might  |  | 
|   941 ** not have an open file handle at this point. |  | 
|   942 */ |  | 
|   943 static int asyncSectorSize(sqlite3_file *pFile){ |  | 
|   944   UNUSED_PARAMETER(pFile); |  | 
|   945   return 512; |  | 
|   946 } |  | 
|   947 static int asyncDeviceCharacteristics(sqlite3_file *pFile){ |  | 
|   948   UNUSED_PARAMETER(pFile); |  | 
|   949   return 0; |  | 
|   950 } |  | 
|   951  |  | 
|   952 static int unlinkAsyncFile(AsyncFileData *pData){ |  | 
|   953   AsyncFileLock **ppIter; |  | 
|   954   int rc = SQLITE_OK; |  | 
|   955  |  | 
|   956   if( pData->zName ){ |  | 
|   957     AsyncLock *pLock = pData->pLock; |  | 
|   958     for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){ |  | 
|   959       if( (*ppIter)==&pData->lock ){ |  | 
|   960         *ppIter = pData->lock.pNext; |  | 
|   961         break; |  | 
|   962       } |  | 
|   963     } |  | 
|   964     if( !pLock->pList ){ |  | 
|   965       AsyncLock **pp; |  | 
|   966       if( pLock->pFile ){ |  | 
|   967         pLock->pFile->pMethods->xClose(pLock->pFile); |  | 
|   968       } |  | 
|   969       for(pp=&async.pLock; *pp!=pLock; pp=&((*pp)->pNext)); |  | 
|   970       *pp = pLock->pNext; |  | 
|   971       sqlite3_free(pLock); |  | 
|   972     }else{ |  | 
|   973       rc = getFileLock(pLock); |  | 
|   974     } |  | 
|   975   } |  | 
|   976  |  | 
|   977   return rc; |  | 
|   978 } |  | 
|   979  |  | 
|   980 /* |  | 
|   981 ** The parameter passed to this function is a copy of a 'flags' parameter |  | 
|   982 ** passed to this modules xOpen() method. This function returns true |  | 
|   983 ** if the file should be opened asynchronously, or false if it should |  | 
|   984 ** be opened immediately. |  | 
|   985 ** |  | 
|   986 ** If the file is to be opened asynchronously, then asyncOpen() will add |  | 
|   987 ** an entry to the event queue and the file will not actually be opened |  | 
|   988 ** until the event is processed. Otherwise, the file is opened directly |  | 
|   989 ** by the caller. |  | 
|   990 */ |  | 
|   991 static int doAsynchronousOpen(int flags){ |  | 
|   992   return (flags&SQLITE_OPEN_CREATE) && ( |  | 
|   993       (flags&SQLITE_OPEN_MAIN_JOURNAL) || |  | 
|   994       (flags&SQLITE_OPEN_TEMP_JOURNAL) || |  | 
|   995       (flags&SQLITE_OPEN_DELETEONCLOSE) |  | 
|   996   ); |  | 
|   997 } |  | 
|   998  |  | 
|   999 /* |  | 
|  1000 ** Open a file. |  | 
|  1001 */ |  | 
|  1002 static int asyncOpen( |  | 
|  1003   sqlite3_vfs *pAsyncVfs, |  | 
|  1004   const char *zName, |  | 
|  1005   sqlite3_file *pFile, |  | 
|  1006   int flags, |  | 
|  1007   int *pOutFlags |  | 
|  1008 ){ |  | 
|  1009   static sqlite3_io_methods async_methods = { |  | 
|  1010     1,                               /* iVersion */ |  | 
|  1011     asyncClose,                      /* xClose */ |  | 
|  1012     asyncRead,                       /* xRead */ |  | 
|  1013     asyncWrite,                      /* xWrite */ |  | 
|  1014     asyncTruncate,                   /* xTruncate */ |  | 
|  1015     asyncSync,                       /* xSync */ |  | 
|  1016     asyncFileSize,                   /* xFileSize */ |  | 
|  1017     asyncLock,                       /* xLock */ |  | 
|  1018     asyncUnlock,                     /* xUnlock */ |  | 
|  1019     asyncCheckReservedLock,          /* xCheckReservedLock */ |  | 
|  1020     asyncFileControl,                /* xFileControl */ |  | 
|  1021     asyncSectorSize,                 /* xSectorSize */ |  | 
|  1022     asyncDeviceCharacteristics       /* xDeviceCharacteristics */ |  | 
|  1023   }; |  | 
|  1024  |  | 
|  1025   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1026   AsyncFile *p = (AsyncFile *)pFile; |  | 
|  1027   int nName = 0; |  | 
|  1028   int rc = SQLITE_OK; |  | 
|  1029   int nByte; |  | 
|  1030   AsyncFileData *pData; |  | 
|  1031   AsyncLock *pLock = 0; |  | 
|  1032   char *z; |  | 
|  1033   int isAsyncOpen = doAsynchronousOpen(flags); |  | 
|  1034  |  | 
|  1035   /* If zName is NULL, then the upper layer is requesting an anonymous file */ |  | 
|  1036   if( zName ){ |  | 
|  1037     nName = (int)strlen(zName)+1; |  | 
|  1038   } |  | 
|  1039  |  | 
|  1040   nByte = ( |  | 
|  1041     sizeof(AsyncFileData) +        /* AsyncFileData structure */ |  | 
|  1042     2 * pVfs->szOsFile +           /* AsyncFileData.pBaseRead and pBaseWrite */ |  | 
|  1043     nName                          /* AsyncFileData.zName */ |  | 
|  1044   );  |  | 
|  1045   z = sqlite3_malloc(nByte); |  | 
|  1046   if( !z ){ |  | 
|  1047     return SQLITE_NOMEM; |  | 
|  1048   } |  | 
|  1049   memset(z, 0, nByte); |  | 
|  1050   pData = (AsyncFileData*)z; |  | 
|  1051   z += sizeof(pData[0]); |  | 
|  1052   pData->pBaseRead = (sqlite3_file*)z; |  | 
|  1053   z += pVfs->szOsFile; |  | 
|  1054   pData->pBaseWrite = (sqlite3_file*)z; |  | 
|  1055   pData->closeOp.pFileData = pData; |  | 
|  1056   pData->closeOp.op = ASYNC_CLOSE; |  | 
|  1057  |  | 
|  1058   if( zName ){ |  | 
|  1059     z += pVfs->szOsFile; |  | 
|  1060     pData->zName = z; |  | 
|  1061     pData->nName = nName; |  | 
|  1062     memcpy(pData->zName, zName, nName); |  | 
|  1063   } |  | 
|  1064  |  | 
|  1065   if( !isAsyncOpen ){ |  | 
|  1066     int flagsout; |  | 
|  1067     rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, &flagsout); |  | 
|  1068     if( rc==SQLITE_OK  |  | 
|  1069      && (flagsout&SQLITE_OPEN_READWRITE)  |  | 
|  1070      && (flags&SQLITE_OPEN_EXCLUSIVE)==0 |  | 
|  1071     ){ |  | 
|  1072       rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseWrite, flags, 0); |  | 
|  1073     } |  | 
|  1074     if( pOutFlags ){ |  | 
|  1075       *pOutFlags = flagsout; |  | 
|  1076     } |  | 
|  1077   } |  | 
|  1078  |  | 
|  1079   async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|  1080  |  | 
|  1081   if( zName && rc==SQLITE_OK ){ |  | 
|  1082     pLock = findLock(pData->zName, pData->nName); |  | 
|  1083     if( !pLock ){ |  | 
|  1084       int nByte = pVfs->szOsFile + sizeof(AsyncLock) + pData->nName + 1;  |  | 
|  1085       pLock = (AsyncLock *)sqlite3_malloc(nByte); |  | 
|  1086       if( pLock ){ |  | 
|  1087         memset(pLock, 0, nByte); |  | 
|  1088         if( async.bLockFiles && (flags&SQLITE_OPEN_MAIN_DB) ){ |  | 
|  1089           pLock->pFile = (sqlite3_file *)&pLock[1]; |  | 
|  1090           rc = pVfs->xOpen(pVfs, pData->zName, pLock->pFile, flags, 0); |  | 
|  1091           if( rc!=SQLITE_OK ){ |  | 
|  1092             sqlite3_free(pLock); |  | 
|  1093             pLock = 0; |  | 
|  1094           } |  | 
|  1095         } |  | 
|  1096         if( pLock ){ |  | 
|  1097           pLock->nFile = pData->nName; |  | 
|  1098           pLock->zFile = &((char *)(&pLock[1]))[pVfs->szOsFile]; |  | 
|  1099           memcpy(pLock->zFile, pData->zName, pLock->nFile); |  | 
|  1100           pLock->pNext = async.pLock; |  | 
|  1101           async.pLock = pLock; |  | 
|  1102         } |  | 
|  1103       }else{ |  | 
|  1104         rc = SQLITE_NOMEM; |  | 
|  1105       } |  | 
|  1106     } |  | 
|  1107   } |  | 
|  1108  |  | 
|  1109   if( rc==SQLITE_OK ){ |  | 
|  1110     p->pMethod = &async_methods; |  | 
|  1111     p->pData = pData; |  | 
|  1112  |  | 
|  1113     /* Link AsyncFileData.lock into the linked list of  |  | 
|  1114     ** AsyncFileLock structures for this file. |  | 
|  1115     */ |  | 
|  1116     if( zName ){ |  | 
|  1117       pData->lock.pNext = pLock->pList; |  | 
|  1118       pLock->pList = &pData->lock; |  | 
|  1119       pData->zName = pLock->zFile; |  | 
|  1120     } |  | 
|  1121   }else{ |  | 
|  1122     if( pData->pBaseRead->pMethods ){ |  | 
|  1123       pData->pBaseRead->pMethods->xClose(pData->pBaseRead); |  | 
|  1124     } |  | 
|  1125     if( pData->pBaseWrite->pMethods ){ |  | 
|  1126       pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite); |  | 
|  1127     } |  | 
|  1128     sqlite3_free(pData); |  | 
|  1129   } |  | 
|  1130  |  | 
|  1131   async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|  1132  |  | 
|  1133   if( rc==SQLITE_OK ){ |  | 
|  1134     incrOpenFileCount(); |  | 
|  1135     pData->pLock = pLock; |  | 
|  1136   } |  | 
|  1137  |  | 
|  1138   if( rc==SQLITE_OK && isAsyncOpen ){ |  | 
|  1139     rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (sqlite3_int64)flags,0,0); |  | 
|  1140     if( rc==SQLITE_OK ){ |  | 
|  1141       if( pOutFlags ) *pOutFlags = flags; |  | 
|  1142     }else{ |  | 
|  1143       async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|  1144       unlinkAsyncFile(pData); |  | 
|  1145       async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|  1146       sqlite3_free(pData); |  | 
|  1147     } |  | 
|  1148   } |  | 
|  1149   if( rc!=SQLITE_OK ){ |  | 
|  1150     p->pMethod = 0; |  | 
|  1151   } |  | 
|  1152   return rc; |  | 
|  1153 } |  | 
|  1154  |  | 
|  1155 /* |  | 
|  1156 ** Implementation of sqlite3OsDelete. Add an entry to the end of the  |  | 
|  1157 ** write-op queue to perform the delete. |  | 
|  1158 */ |  | 
|  1159 static int asyncDelete(sqlite3_vfs *pAsyncVfs, const char *z, int syncDir){ |  | 
|  1160   UNUSED_PARAMETER(pAsyncVfs); |  | 
|  1161   return addNewAsyncWrite(0, ASYNC_DELETE, syncDir, (int)strlen(z)+1, z); |  | 
|  1162 } |  | 
|  1163  |  | 
|  1164 /* |  | 
|  1165 ** Implementation of sqlite3OsAccess. This method holds the mutex from |  | 
|  1166 ** start to finish. |  | 
|  1167 */ |  | 
|  1168 static int asyncAccess( |  | 
|  1169   sqlite3_vfs *pAsyncVfs,  |  | 
|  1170   const char *zName,  |  | 
|  1171   int flags, |  | 
|  1172   int *pResOut |  | 
|  1173 ){ |  | 
|  1174   int rc; |  | 
|  1175   int ret; |  | 
|  1176   AsyncWrite *p; |  | 
|  1177   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1178  |  | 
|  1179   assert(flags==SQLITE_ACCESS_READWRITE  |  | 
|  1180       || flags==SQLITE_ACCESS_READ  |  | 
|  1181       || flags==SQLITE_ACCESS_EXISTS  |  | 
|  1182   ); |  | 
|  1183  |  | 
|  1184   async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1185   rc = pVfs->xAccess(pVfs, zName, flags, &ret); |  | 
|  1186   if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ |  | 
|  1187     for(p=async.pQueueFirst; p; p = p->pNext){ |  | 
|  1188       if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){ |  | 
|  1189         ret = 0; |  | 
|  1190       }else if( p->op==ASYNC_OPENEXCLUSIVE  |  | 
|  1191              && p->pFileData->zName |  | 
|  1192              && 0==strcmp(p->pFileData->zName, zName)  |  | 
|  1193       ){ |  | 
|  1194         ret = 1; |  | 
|  1195       } |  | 
|  1196     } |  | 
|  1197   } |  | 
|  1198   ASYNC_TRACE(("ACCESS(%s): %s = %d\n",  |  | 
|  1199     flags==SQLITE_ACCESS_READWRITE?"read-write": |  | 
|  1200     flags==SQLITE_ACCESS_READ?"read":"exists" |  | 
|  1201     , zName, ret) |  | 
|  1202   ); |  | 
|  1203   async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1204   *pResOut = ret; |  | 
|  1205   return rc; |  | 
|  1206 } |  | 
|  1207  |  | 
|  1208 /* |  | 
|  1209 ** Fill in zPathOut with the full path to the file identified by zPath. |  | 
|  1210 */ |  | 
|  1211 static int asyncFullPathname( |  | 
|  1212   sqlite3_vfs *pAsyncVfs,  |  | 
|  1213   const char *zPath,  |  | 
|  1214   int nPathOut, |  | 
|  1215   char *zPathOut |  | 
|  1216 ){ |  | 
|  1217   int rc; |  | 
|  1218   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1219   rc = pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); |  | 
|  1220  |  | 
|  1221   /* Because of the way intra-process file locking works, this backend |  | 
|  1222   ** needs to return a canonical path. The following block assumes the |  | 
|  1223   ** file-system uses unix style paths.  |  | 
|  1224   */ |  | 
|  1225   if( rc==SQLITE_OK ){ |  | 
|  1226     int i, j; |  | 
|  1227     int n = nPathOut; |  | 
|  1228     char *z = zPathOut; |  | 
|  1229     while( n>1 && z[n-1]=='/' ){ n--; } |  | 
|  1230     for(i=j=0; i<n; i++){ |  | 
|  1231       if( z[i]=='/' ){ |  | 
|  1232         if( z[i+1]=='/' ) continue; |  | 
|  1233         if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){ |  | 
|  1234           i += 1; |  | 
|  1235           continue; |  | 
|  1236         } |  | 
|  1237         if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){ |  | 
|  1238           while( j>0 && z[j-1]!='/' ){ j--; } |  | 
|  1239           if( j>0 ){ j--; } |  | 
|  1240           i += 2; |  | 
|  1241           continue; |  | 
|  1242         } |  | 
|  1243       } |  | 
|  1244       z[j++] = z[i]; |  | 
|  1245     } |  | 
|  1246     z[j] = 0; |  | 
|  1247   } |  | 
|  1248  |  | 
|  1249   return rc; |  | 
|  1250 } |  | 
|  1251 static void *asyncDlOpen(sqlite3_vfs *pAsyncVfs, const char *zPath){ |  | 
|  1252   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1253   return pVfs->xDlOpen(pVfs, zPath); |  | 
|  1254 } |  | 
|  1255 static void asyncDlError(sqlite3_vfs *pAsyncVfs, int nByte, char *zErrMsg){ |  | 
|  1256   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1257   pVfs->xDlError(pVfs, nByte, zErrMsg); |  | 
|  1258 } |  | 
|  1259 static void (*asyncDlSym( |  | 
|  1260   sqlite3_vfs *pAsyncVfs,  |  | 
|  1261   void *pHandle,  |  | 
|  1262   const char *zSymbol |  | 
|  1263 ))(void){ |  | 
|  1264   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1265   return pVfs->xDlSym(pVfs, pHandle, zSymbol); |  | 
|  1266 } |  | 
|  1267 static void asyncDlClose(sqlite3_vfs *pAsyncVfs, void *pHandle){ |  | 
|  1268   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1269   pVfs->xDlClose(pVfs, pHandle); |  | 
|  1270 } |  | 
|  1271 static int asyncRandomness(sqlite3_vfs *pAsyncVfs, int nByte, char *zBufOut){ |  | 
|  1272   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1273   return pVfs->xRandomness(pVfs, nByte, zBufOut); |  | 
|  1274 } |  | 
|  1275 static int asyncSleep(sqlite3_vfs *pAsyncVfs, int nMicro){ |  | 
|  1276   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1277   return pVfs->xSleep(pVfs, nMicro); |  | 
|  1278 } |  | 
|  1279 static int asyncCurrentTime(sqlite3_vfs *pAsyncVfs, double *pTimeOut){ |  | 
|  1280   sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData; |  | 
|  1281   return pVfs->xCurrentTime(pVfs, pTimeOut); |  | 
|  1282 } |  | 
|  1283  |  | 
|  1284 static sqlite3_vfs async_vfs = { |  | 
|  1285   1,                    /* iVersion */ |  | 
|  1286   sizeof(AsyncFile),    /* szOsFile */ |  | 
|  1287   0,                    /* mxPathname */ |  | 
|  1288   0,                    /* pNext */ |  | 
|  1289   SQLITEASYNC_VFSNAME,  /* zName */ |  | 
|  1290   0,                    /* pAppData */ |  | 
|  1291   asyncOpen,            /* xOpen */ |  | 
|  1292   asyncDelete,          /* xDelete */ |  | 
|  1293   asyncAccess,          /* xAccess */ |  | 
|  1294   asyncFullPathname,    /* xFullPathname */ |  | 
|  1295   asyncDlOpen,          /* xDlOpen */ |  | 
|  1296   asyncDlError,         /* xDlError */ |  | 
|  1297   asyncDlSym,           /* xDlSym */ |  | 
|  1298   asyncDlClose,         /* xDlClose */ |  | 
|  1299   asyncRandomness,      /* xDlError */ |  | 
|  1300   asyncSleep,           /* xDlSym */ |  | 
|  1301   asyncCurrentTime      /* xDlClose */ |  | 
|  1302 }; |  | 
|  1303  |  | 
|  1304 /*  |  | 
|  1305 ** This procedure runs in a separate thread, reading messages off of the |  | 
|  1306 ** write queue and processing them one by one.   |  | 
|  1307 ** |  | 
|  1308 ** If async.writerHaltNow is true, then this procedure exits |  | 
|  1309 ** after processing a single message. |  | 
|  1310 ** |  | 
|  1311 ** If async.writerHaltWhenIdle is true, then this procedure exits when |  | 
|  1312 ** the write queue is empty. |  | 
|  1313 ** |  | 
|  1314 ** If both of the above variables are false, this procedure runs |  | 
|  1315 ** indefinately, waiting for operations to be added to the write queue |  | 
|  1316 ** and processing them in the order in which they arrive. |  | 
|  1317 ** |  | 
|  1318 ** An artifical delay of async.ioDelay milliseconds is inserted before |  | 
|  1319 ** each write operation in order to simulate the effect of a slow disk. |  | 
|  1320 ** |  | 
|  1321 ** Only one instance of this procedure may be running at a time. |  | 
|  1322 */ |  | 
|  1323 static void asyncWriterThread(void){ |  | 
|  1324   sqlite3_vfs *pVfs = (sqlite3_vfs *)(async_vfs.pAppData); |  | 
|  1325   AsyncWrite *p = 0; |  | 
|  1326   int rc = SQLITE_OK; |  | 
|  1327   int holdingMutex = 0; |  | 
|  1328  |  | 
|  1329   async_mutex_enter(ASYNC_MUTEX_WRITER); |  | 
|  1330  |  | 
|  1331   while( async.eHalt!=SQLITEASYNC_HALT_NOW ){ |  | 
|  1332     int doNotFree = 0; |  | 
|  1333     sqlite3_file *pBase = 0; |  | 
|  1334  |  | 
|  1335     if( !holdingMutex ){ |  | 
|  1336       async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1337     } |  | 
|  1338     while( (p = async.pQueueFirst)==0 ){ |  | 
|  1339       if( async.eHalt!=SQLITEASYNC_HALT_NEVER ){ |  | 
|  1340         async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1341         break; |  | 
|  1342       }else{ |  | 
|  1343         ASYNC_TRACE(("IDLE\n")); |  | 
|  1344         async_cond_wait(ASYNC_COND_QUEUE, ASYNC_MUTEX_QUEUE); |  | 
|  1345         ASYNC_TRACE(("WAKEUP\n")); |  | 
|  1346       } |  | 
|  1347     } |  | 
|  1348     if( p==0 ) break; |  | 
|  1349     holdingMutex = 1; |  | 
|  1350  |  | 
|  1351     /* Right now this thread is holding the mutex on the write-op queue. |  | 
|  1352     ** Variable 'p' points to the first entry in the write-op queue. In |  | 
|  1353     ** the general case, we hold on to the mutex for the entire body of |  | 
|  1354     ** the loop.  |  | 
|  1355     ** |  | 
|  1356     ** However in the cases enumerated below, we relinquish the mutex, |  | 
|  1357     ** perform the IO, and then re-request the mutex before removing 'p' from |  | 
|  1358     ** the head of the write-op queue. The idea is to increase concurrency with |  | 
|  1359     ** sqlite threads. |  | 
|  1360     ** |  | 
|  1361     **     * An ASYNC_CLOSE operation. |  | 
|  1362     **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish  |  | 
|  1363     **       the mutex, call the underlying xOpenExclusive() function, then |  | 
|  1364     **       re-aquire the mutex before seting the AsyncFile.pBaseRead  |  | 
|  1365     **       variable. |  | 
|  1366     **     * ASYNC_SYNC and ASYNC_WRITE operations, if  |  | 
|  1367     **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two |  | 
|  1368     **       file-handles are open for the particular file being "synced". |  | 
|  1369     */ |  | 
|  1370     if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){ |  | 
|  1371       p->op = ASYNC_NOOP; |  | 
|  1372     } |  | 
|  1373     if( p->pFileData ){ |  | 
|  1374       pBase = p->pFileData->pBaseWrite; |  | 
|  1375       if(  |  | 
|  1376         p->op==ASYNC_CLOSE ||  |  | 
|  1377         p->op==ASYNC_OPENEXCLUSIVE || |  | 
|  1378         (pBase->pMethods && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) )  |  | 
|  1379       ){ |  | 
|  1380         async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1381         holdingMutex = 0; |  | 
|  1382       } |  | 
|  1383       if( !pBase->pMethods ){ |  | 
|  1384         pBase = p->pFileData->pBaseRead; |  | 
|  1385       } |  | 
|  1386     } |  | 
|  1387  |  | 
|  1388     switch( p->op ){ |  | 
|  1389       case ASYNC_NOOP: |  | 
|  1390         break; |  | 
|  1391  |  | 
|  1392       case ASYNC_WRITE: |  | 
|  1393         assert( pBase ); |  | 
|  1394         ASYNC_TRACE(("WRITE %s %d bytes at %d\n", |  | 
|  1395                 p->pFileData->zName, p->nByte, p->iOffset)); |  | 
|  1396         rc = pBase->pMethods->xWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOff
      set); |  | 
|  1397         break; |  | 
|  1398  |  | 
|  1399       case ASYNC_SYNC: |  | 
|  1400         assert( pBase ); |  | 
|  1401         ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName)); |  | 
|  1402         rc = pBase->pMethods->xSync(pBase, p->nByte); |  | 
|  1403         break; |  | 
|  1404  |  | 
|  1405       case ASYNC_TRUNCATE: |  | 
|  1406         assert( pBase ); |  | 
|  1407         ASYNC_TRACE(("TRUNCATE %s to %d bytes\n",  |  | 
|  1408                 p->pFileData->zName, p->iOffset)); |  | 
|  1409         rc = pBase->pMethods->xTruncate(pBase, p->iOffset); |  | 
|  1410         break; |  | 
|  1411  |  | 
|  1412       case ASYNC_CLOSE: { |  | 
|  1413         AsyncFileData *pData = p->pFileData; |  | 
|  1414         ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName)); |  | 
|  1415         if( pData->pBaseWrite->pMethods ){ |  | 
|  1416           pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite); |  | 
|  1417         } |  | 
|  1418         if( pData->pBaseRead->pMethods ){ |  | 
|  1419           pData->pBaseRead->pMethods->xClose(pData->pBaseRead); |  | 
|  1420         } |  | 
|  1421  |  | 
|  1422         /* Unlink AsyncFileData.lock from the linked list of AsyncFileLock  |  | 
|  1423         ** structures for this file. Obtain the async.lockMutex mutex  |  | 
|  1424         ** before doing so. |  | 
|  1425         */ |  | 
|  1426         async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|  1427         rc = unlinkAsyncFile(pData); |  | 
|  1428         async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|  1429  |  | 
|  1430         if( !holdingMutex ){ |  | 
|  1431           async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1432           holdingMutex = 1; |  | 
|  1433         } |  | 
|  1434         assert_mutex_is_held(ASYNC_MUTEX_QUEUE); |  | 
|  1435         async.pQueueFirst = p->pNext; |  | 
|  1436         sqlite3_free(pData); |  | 
|  1437         doNotFree = 1; |  | 
|  1438         break; |  | 
|  1439       } |  | 
|  1440  |  | 
|  1441       case ASYNC_UNLOCK: { |  | 
|  1442         AsyncWrite *pIter; |  | 
|  1443         AsyncFileData *pData = p->pFileData; |  | 
|  1444         int eLock = p->nByte; |  | 
|  1445  |  | 
|  1446         /* When a file is locked by SQLite using the async backend, it is  |  | 
|  1447         ** locked within the 'real' file-system synchronously. When it is |  | 
|  1448         ** unlocked, an ASYNC_UNLOCK event is added to the write-queue to |  | 
|  1449         ** unlock the file asynchronously. The design of the async backend |  | 
|  1450         ** requires that the 'real' file-system file be locked from the |  | 
|  1451         ** time that SQLite first locks it (and probably reads from it) |  | 
|  1452         ** until all asynchronous write events that were scheduled before |  | 
|  1453         ** SQLite unlocked the file have been processed. |  | 
|  1454         ** |  | 
|  1455         ** This is more complex if SQLite locks and unlocks the file multiple |  | 
|  1456         ** times in quick succession. For example, if SQLite does:  |  | 
|  1457         **  |  | 
|  1458         **   lock, write, unlock, lock, write, unlock |  | 
|  1459         ** |  | 
|  1460         ** Each "lock" operation locks the file immediately. Each "write"  |  | 
|  1461         ** and "unlock" operation adds an event to the event queue. If the |  | 
|  1462         ** second "lock" operation is performed before the first "unlock" |  | 
|  1463         ** operation has been processed asynchronously, then the first |  | 
|  1464         ** "unlock" cannot be safely processed as is, since this would mean |  | 
|  1465         ** the file was unlocked when the second "write" operation is |  | 
|  1466         ** processed. To work around this, when processing an ASYNC_UNLOCK |  | 
|  1467         ** operation, SQLite: |  | 
|  1468         ** |  | 
|  1469         **   1) Unlocks the file to the minimum of the argument passed to |  | 
|  1470         **      the xUnlock() call and the current lock from SQLite's point |  | 
|  1471         **      of view, and |  | 
|  1472         ** |  | 
|  1473         **   2) Only unlocks the file at all if this event is the last |  | 
|  1474         **      ASYNC_UNLOCK event on this file in the write-queue. |  | 
|  1475         */  |  | 
|  1476         assert( holdingMutex==1 ); |  | 
|  1477         assert( async.pQueueFirst==p ); |  | 
|  1478         for(pIter=async.pQueueFirst->pNext; pIter; pIter=pIter->pNext){ |  | 
|  1479           if( pIter->pFileData==pData && pIter->op==ASYNC_UNLOCK ) break; |  | 
|  1480         } |  | 
|  1481         if( !pIter ){ |  | 
|  1482           async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|  1483           pData->lock.eAsyncLock = MIN( |  | 
|  1484               pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock) |  | 
|  1485           ); |  | 
|  1486           assert(pData->lock.eAsyncLock>=pData->lock.eLock); |  | 
|  1487           rc = getFileLock(pData->pLock); |  | 
|  1488           async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|  1489         } |  | 
|  1490         break; |  | 
|  1491       } |  | 
|  1492  |  | 
|  1493       case ASYNC_DELETE: |  | 
|  1494         ASYNC_TRACE(("DELETE %s\n", p->zBuf)); |  | 
|  1495         rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset); |  | 
|  1496         break; |  | 
|  1497  |  | 
|  1498       case ASYNC_OPENEXCLUSIVE: { |  | 
|  1499         int flags = (int)p->iOffset; |  | 
|  1500         AsyncFileData *pData = p->pFileData; |  | 
|  1501         ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset)); |  | 
|  1502         assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0); |  | 
|  1503         rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0); |  | 
|  1504         assert( holdingMutex==0 ); |  | 
|  1505         async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1506         holdingMutex = 1; |  | 
|  1507         break; |  | 
|  1508       } |  | 
|  1509  |  | 
|  1510       default: assert(!"Illegal value for AsyncWrite.op"); |  | 
|  1511     } |  | 
|  1512  |  | 
|  1513     /* If we didn't hang on to the mutex during the IO op, obtain it now |  | 
|  1514     ** so that the AsyncWrite structure can be safely removed from the  |  | 
|  1515     ** global write-op queue. |  | 
|  1516     */ |  | 
|  1517     if( !holdingMutex ){ |  | 
|  1518       async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1519       holdingMutex = 1; |  | 
|  1520     } |  | 
|  1521     /* ASYNC_TRACE(("UNLINK %p\n", p)); */ |  | 
|  1522     if( p==async.pQueueLast ){ |  | 
|  1523       async.pQueueLast = 0; |  | 
|  1524     } |  | 
|  1525     if( !doNotFree ){ |  | 
|  1526       assert_mutex_is_held(ASYNC_MUTEX_QUEUE); |  | 
|  1527       async.pQueueFirst = p->pNext; |  | 
|  1528       sqlite3_free(p); |  | 
|  1529     } |  | 
|  1530     assert( holdingMutex ); |  | 
|  1531  |  | 
|  1532     /* An IO error has occurred. We cannot report the error back to the |  | 
|  1533     ** connection that requested the I/O since the error happened  |  | 
|  1534     ** asynchronously.  The connection has already moved on.  There  |  | 
|  1535     ** really is nobody to report the error to. |  | 
|  1536     ** |  | 
|  1537     ** The file for which the error occurred may have been a database or |  | 
|  1538     ** journal file. Regardless, none of the currently queued operations |  | 
|  1539     ** associated with the same database should now be performed. Nor should |  | 
|  1540     ** any subsequently requested IO on either a database or journal file  |  | 
|  1541     ** handle for the same database be accepted until the main database |  | 
|  1542     ** file handle has been closed and reopened. |  | 
|  1543     ** |  | 
|  1544     ** Furthermore, no further IO should be queued or performed on any file |  | 
|  1545     ** handle associated with a database that may have been part of a  |  | 
|  1546     ** multi-file transaction that included the database associated with  |  | 
|  1547     ** the IO error (i.e. a database ATTACHed to the same handle at some  |  | 
|  1548     ** point in time). |  | 
|  1549     */ |  | 
|  1550     if( rc!=SQLITE_OK ){ |  | 
|  1551       async.ioError = rc; |  | 
|  1552     } |  | 
|  1553  |  | 
|  1554     if( async.ioError && !async.pQueueFirst ){ |  | 
|  1555       async_mutex_enter(ASYNC_MUTEX_LOCK); |  | 
|  1556       if( 0==async.pLock ){ |  | 
|  1557         async.ioError = SQLITE_OK; |  | 
|  1558       } |  | 
|  1559       async_mutex_leave(ASYNC_MUTEX_LOCK); |  | 
|  1560     } |  | 
|  1561  |  | 
|  1562     /* Drop the queue mutex before continuing to the next write operation |  | 
|  1563     ** in order to give other threads a chance to work with the write queue. |  | 
|  1564     */ |  | 
|  1565     if( !async.pQueueFirst || !async.ioError ){ |  | 
|  1566       async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1567       holdingMutex = 0; |  | 
|  1568       if( async.ioDelay>0 ){ |  | 
|  1569         pVfs->xSleep(pVfs, async.ioDelay*1000); |  | 
|  1570       }else{ |  | 
|  1571         async_sched_yield(); |  | 
|  1572       } |  | 
|  1573     } |  | 
|  1574   } |  | 
|  1575    |  | 
|  1576   async_mutex_leave(ASYNC_MUTEX_WRITER); |  | 
|  1577   return; |  | 
|  1578 } |  | 
|  1579  |  | 
|  1580 /* |  | 
|  1581 ** Install the asynchronous VFS. |  | 
|  1582 */  |  | 
|  1583 int sqlite3async_initialize(const char *zParent, int isDefault){ |  | 
|  1584   int rc = SQLITE_OK; |  | 
|  1585   if( async_vfs.pAppData==0 ){ |  | 
|  1586     sqlite3_vfs *pParent = sqlite3_vfs_find(zParent); |  | 
|  1587     if( !pParent || async_os_initialize() ){ |  | 
|  1588       rc = SQLITE_ERROR; |  | 
|  1589     }else if( SQLITE_OK!=(rc = sqlite3_vfs_register(&async_vfs, isDefault)) ){ |  | 
|  1590       async_os_shutdown(); |  | 
|  1591     }else{ |  | 
|  1592       async_vfs.pAppData = (void *)pParent; |  | 
|  1593       async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname; |  | 
|  1594     } |  | 
|  1595   } |  | 
|  1596   return rc; |  | 
|  1597 } |  | 
|  1598  |  | 
|  1599 /* |  | 
|  1600 ** Uninstall the asynchronous VFS. |  | 
|  1601 */ |  | 
|  1602 void sqlite3async_shutdown(void){ |  | 
|  1603   if( async_vfs.pAppData ){ |  | 
|  1604     async_os_shutdown(); |  | 
|  1605     sqlite3_vfs_unregister((sqlite3_vfs *)&async_vfs); |  | 
|  1606     async_vfs.pAppData = 0; |  | 
|  1607   } |  | 
|  1608 } |  | 
|  1609  |  | 
|  1610 /* |  | 
|  1611 ** Process events on the write-queue. |  | 
|  1612 */ |  | 
|  1613 void sqlite3async_run(void){ |  | 
|  1614   asyncWriterThread(); |  | 
|  1615 } |  | 
|  1616  |  | 
|  1617 /* |  | 
|  1618 ** Control/configure the asynchronous IO system. |  | 
|  1619 */ |  | 
|  1620 int sqlite3async_control(int op, ...){ |  | 
|  1621   va_list ap; |  | 
|  1622   va_start(ap, op); |  | 
|  1623   switch( op ){ |  | 
|  1624     case SQLITEASYNC_HALT: { |  | 
|  1625       int eWhen = va_arg(ap, int); |  | 
|  1626       if( eWhen!=SQLITEASYNC_HALT_NEVER |  | 
|  1627        && eWhen!=SQLITEASYNC_HALT_NOW |  | 
|  1628        && eWhen!=SQLITEASYNC_HALT_IDLE |  | 
|  1629       ){ |  | 
|  1630         return SQLITE_MISUSE; |  | 
|  1631       } |  | 
|  1632       async.eHalt = eWhen; |  | 
|  1633       async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1634       async_cond_signal(ASYNC_COND_QUEUE); |  | 
|  1635       async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1636       break; |  | 
|  1637     } |  | 
|  1638  |  | 
|  1639     case SQLITEASYNC_DELAY: { |  | 
|  1640       int iDelay = va_arg(ap, int); |  | 
|  1641       if( iDelay<0 ){ |  | 
|  1642         return SQLITE_MISUSE; |  | 
|  1643       } |  | 
|  1644       async.ioDelay = iDelay; |  | 
|  1645       break; |  | 
|  1646     } |  | 
|  1647  |  | 
|  1648     case SQLITEASYNC_LOCKFILES: { |  | 
|  1649       int bLock = va_arg(ap, int); |  | 
|  1650       async_mutex_enter(ASYNC_MUTEX_QUEUE); |  | 
|  1651       if( async.nFile || async.pQueueFirst ){ |  | 
|  1652         async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1653         return SQLITE_MISUSE; |  | 
|  1654       } |  | 
|  1655       async.bLockFiles = bLock; |  | 
|  1656       async_mutex_leave(ASYNC_MUTEX_QUEUE); |  | 
|  1657       break; |  | 
|  1658     } |  | 
|  1659        |  | 
|  1660     case SQLITEASYNC_GET_HALT: { |  | 
|  1661       int *peWhen = va_arg(ap, int *); |  | 
|  1662       *peWhen = async.eHalt; |  | 
|  1663       break; |  | 
|  1664     } |  | 
|  1665     case SQLITEASYNC_GET_DELAY: { |  | 
|  1666       int *piDelay = va_arg(ap, int *); |  | 
|  1667       *piDelay = async.ioDelay; |  | 
|  1668       break; |  | 
|  1669     } |  | 
|  1670     case SQLITEASYNC_GET_LOCKFILES: { |  | 
|  1671       int *piDelay = va_arg(ap, int *); |  | 
|  1672       *piDelay = async.bLockFiles; |  | 
|  1673       break; |  | 
|  1674     } |  | 
|  1675  |  | 
|  1676     default: |  | 
|  1677       return SQLITE_ERROR; |  | 
|  1678   } |  | 
|  1679   return SQLITE_OK; |  | 
|  1680 } |  | 
|  1681  |  | 
|  1682 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */ |  | 
|  1683  |  | 
| OLD | NEW |