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