Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch wal-refactor Excluding Merge-Ins
This is equivalent to a diff from 7838163d08 to 149d2ae4a6
2010-05-13
| ||
08:53 | The refactored of VFS SHM primitives are now working so merge the wal-refactor branch back into the trunk. (check-in: bce21c1838 user: drh tags: trunk) | |
08:33 | Change the xShmSize() implementation in os_unix.c so that it will only increase and never decrease the size of a shared-memory segment. (Closed-Leaf check-in: 149d2ae4a6 user: drh tags: wal-refactor) | |
07:08 | Fix for a segfault that can follow a malloc failure. (check-in: 3cab902245 user: dan tags: wal-refactor) | |
2010-05-12
| ||
19:02 | (Moved to the mistake branch due to compile errors in test_osinst.c.) Change the vfs instrumentation code in test_osinst.c to make it easier to deploy. Add a vtab implementation for reading the binary log file format. (check-in: ee13c8849d user: dan tags: mistake) | |
18:01 | Refactoring the VFS-SHM methods used by WAL. This version compiles and runs non-WAL test cases but crashes and burns on wal.test. (check-in: 2b00152c1a user: drh tags: wal-refactor) | |
13:50 | Remove the OP_Variable optimization of check-in [48b77b04935d894] since it can lead to malfunctions as described in ticket [26ff0c82d1e90]. (check-in: 7838163d08 user: drh tags: trunk) | |
06:54 | Remove a branch made redundant by the earlier exclusive-mode changes. (check-in: c501b2ede6 user: dan tags: trunk) | |
Changes to doc/vfs-shm.txt.
74 74 75 75 The SQLite core will obey the next set of rules. These rules are 76 76 assertions on the behavior of the SQLite core which might be verified 77 77 during testing using an instrumented lock manager. 78 78 79 79 (5) No part of the wal-index will be read without holding either some 80 80 kind of SHM lock or an EXCLUSIVE lock on the original database. 81 + The original database is the file named in the 2nd parameter to 82 + the xShmOpen method. 83 + 81 84 (6) A holder of a READ_FULL will never read any page of the database 82 85 file that is contained anywhere in the wal-index. 86 + 83 87 (7) No part of the wal-index other than the header will be written nor 84 - will the size of the wal-index grow without holding a WRITE. 88 + will the size of the wal-index grow without holding a WRITE or 89 + an EXCLUSIVE on the original database file. 90 + 85 91 (8) The wal-index header will not be written without holding one of 86 - WRITE, CHECKPOINT, or RECOVER. 87 -(9) A CHECKPOINT or RECOVER must be held in order to reset the last valid 88 - frame counter in the header of the wal-index back to zero. 92 + WRITE, CHECKPOINT, or RECOVER on the wal-index or an EXCLUSIVE on 93 + the original database files. 94 + 95 +(9) A CHECKPOINT or RECOVER must be held on the wal-index, or an 96 + EXCLUSIVE on the original database file, in order to reset the 97 + last valid frame counter in the header of the wal-index back to zero. 98 + 89 99 (10) A WRITE can only increase the last valid frame pointer in the header. 90 100 91 101 The SQLite core will only ever send requests for UNLOCK, READ, WRITE, 92 102 CHECKPOINT, or RECOVER to the lock manager. The SQLite core will never 93 103 request a READ_FULL or PENDING lock though the lock manager may deliver 94 104 those locking states in response to READ and CHECKPOINT requests, 95 105 respectively, if and only if the requested READ or CHECKPOINT cannot
Changes to src/os.c.
94 94 int sqlite3OsSectorSize(sqlite3_file *id){ 95 95 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; 96 96 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); 97 97 } 98 98 int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ 99 99 return id->pMethods->xDeviceCharacteristics(id); 100 100 } 101 +int sqlite3OsShmOpen(sqlite3_file *id){ 102 + return id->pMethods->xShmOpen(id); 103 +} 104 +int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){ 105 + return id->pMethods->xShmSize(id, reqSize, pNewSize); 106 +} 107 +int sqlite3OsShmGet(sqlite3_file *id, int reqSize, int *pSize, void **pp){ 108 + return id->pMethods->xShmGet(id, reqSize, pSize, pp); 109 +} 110 +int sqlite3OsShmRelease(sqlite3_file *id){ 111 + return id->pMethods->xShmRelease(id); 112 +} 113 +int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){ 114 + return id->pMethods->xShmLock(id, desiredLock, pGotLock); 115 +} 116 +int sqlite3OsShmClose(sqlite3_file *id, int deleteFlag){ 117 + return id->pMethods->xShmClose(id, deleteFlag); 118 +} 101 119 102 120 /* 103 121 ** The next group of routines are convenience wrappers around the 104 122 ** VFS methods. 105 123 */ 106 124 int sqlite3OsOpen( 107 125 sqlite3_vfs *pVfs,
Changes to src/os.h.
239 239 int sqlite3OsLock(sqlite3_file*, int); 240 240 int sqlite3OsUnlock(sqlite3_file*, int); 241 241 int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); 242 242 int sqlite3OsFileControl(sqlite3_file*,int,void*); 243 243 #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 244 244 int sqlite3OsSectorSize(sqlite3_file *id); 245 245 int sqlite3OsDeviceCharacteristics(sqlite3_file *id); 246 +int sqlite3OsShmOpen(sqlite3_file *id); 247 +int sqlite3OsShmSize(sqlite3_file *id, int, int*); 248 +int sqlite3OsShmGet(sqlite3_file *id, int, int*, void**); 249 +int sqlite3OsShmRelease(sqlite3_file *id); 250 +int sqlite3OsShmLock(sqlite3_file *id, int, int*); 251 +int sqlite3OsShmClose(sqlite3_file *id, int); 246 252 247 253 /* 248 254 ** Functions for accessing sqlite3_vfs methods 249 255 */ 250 256 int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); 251 257 int sqlite3OsDelete(sqlite3_vfs *, const char *, int); 252 258 int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
Changes to src/os_unix.c.
171 171 172 172 /* 173 173 ** Only set the lastErrno if the error code is a real error and not 174 174 ** a normal expected return code of SQLITE_BUSY or SQLITE_OK 175 175 */ 176 176 #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) 177 177 178 +/* Forward reference */ 179 +typedef struct unixShm unixShm; 180 +typedef struct unixShmFile unixShmFile; 178 181 179 182 /* 180 183 ** Sometimes, after a file handle is closed by SQLite, the file descriptor 181 184 ** cannot be closed immediately. In these cases, instances of the following 182 185 ** structure are used to store the file descriptor while waiting for an 183 186 ** opportunity to either close or reuse it. 184 187 */ ................................................................................ 201 204 int h; /* The file descriptor */ 202 205 int dirfd; /* File descriptor for the directory */ 203 206 unsigned char locktype; /* The type of lock held on this fd */ 204 207 int lastErrno; /* The unix errno from the last I/O error */ 205 208 void *lockingContext; /* Locking style specific state */ 206 209 UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ 207 210 int fileFlags; /* Miscellanous flags */ 211 + const char *zPath; /* Name of the file */ 212 + unixShm *pShm; /* Shared memory segment information */ 208 213 #if SQLITE_ENABLE_LOCKING_STYLE 209 214 int openFlags; /* The flags specified at open() */ 210 215 #endif 211 216 #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) 212 217 unsigned fsFlags; /* cached details from statfs() */ 213 218 #endif 214 219 #if SQLITE_THREADSAFE && defined(__linux__) ................................................................................ 3396 3401 ** Return the device characteristics for the file. This is always 0 for unix. 3397 3402 */ 3398 3403 static int unixDeviceCharacteristics(sqlite3_file *NotUsed){ 3399 3404 UNUSED_PARAMETER(NotUsed); 3400 3405 return 0; 3401 3406 } 3402 3407 3408 +#ifndef SQLITE_OMIT_WAL 3409 + 3410 + 3411 +/* 3412 +** Object used to represent a single file opened and mmapped to provide 3413 +** shared memory. When multiple threads all reference the same 3414 +** log-summary, each thread has its own unixFile object, but they all 3415 +** point to a single instance of this object. In other words, each 3416 +** log-summary is opened only once per process. 3417 +** 3418 +** unixMutexHeld() must be true when creating or destroying 3419 +** this object or while reading or writing the following fields: 3420 +** 3421 +** nRef 3422 +** pNext 3423 +** 3424 +** The following fields are read-only after the object is created: 3425 +** 3426 +** fid 3427 +** zFilename 3428 +** 3429 +** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and 3430 +** unixMutexHeld() is true when reading or writing any other field 3431 +** in this structure. 3432 +** 3433 +** To avoid deadlocks, mutex and mutexBuf are always released in the 3434 +** reverse order that they are acquired. mutexBuf is always acquired 3435 +** first and released last. This invariant is check by asserting 3436 +** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or 3437 +** released. 3438 +*/ 3439 +struct unixShmFile { 3440 + struct unixFileId fid; /* Unique file identifier */ 3441 + sqlite3_mutex *mutex; /* Mutex to access this object */ 3442 + sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */ 3443 + char *zFilename; /* Name of the mmapped file */ 3444 + int h; /* Open file descriptor */ 3445 + int szMap; /* Size of the mapping of file into memory */ 3446 + char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */ 3447 + int nRef; /* Number of unixShm objects pointing to this */ 3448 + unixShm *pFirst; /* All unixShm objects pointing to this */ 3449 + unixShmFile *pNext; /* Next in list of all unixShmFile objects */ 3450 +#ifdef SQLITE_DEBUG 3451 + u8 exclMask; /* Mask of exclusive locks held */ 3452 + u8 sharedMask; /* Mask of shared locks held */ 3453 + u8 nextShmId; /* Next available unixShm.id value */ 3454 +#endif 3455 +}; 3456 + 3457 +/* 3458 +** A global array of all unixShmFile objects. 3459 +** 3460 +** The unixMutexHeld() must be true while reading or writing this list. 3461 +*/ 3462 +static unixShmFile *unixShmFileList = 0; 3463 + 3464 +/* 3465 +** Structure used internally by this VFS to record the state of an 3466 +** open shared memory connection. 3467 +** 3468 +** unixShm.pFile->mutex must be held while reading or writing the 3469 +** unixShm.pNext and unixShm.locks[] elements. 3470 +** 3471 +** The unixShm.pFile element is initialized when the object is created 3472 +** and is read-only thereafter. 3473 +*/ 3474 +struct unixShm { 3475 + unixShmFile *pFile; /* The underlying unixShmFile object */ 3476 + unixShm *pNext; /* Next unixShm with the same unixShmFile */ 3477 + u8 lockState; /* Current lock state */ 3478 + u8 hasMutex; /* True if holding the unixShmFile mutex */ 3479 + u8 hasMutexBuf; /* True if holding pFile->mutexBuf */ 3480 + u8 sharedMask; /* Mask of shared locks held */ 3481 + u8 exclMask; /* Mask of exclusive locks held */ 3482 +#ifdef SQLITE_DEBUG 3483 + u8 id; /* Id of this connection with its unixShmFile */ 3484 +#endif 3485 +}; 3486 + 3487 +/* 3488 +** Size increment by which shared memory grows 3489 +*/ 3490 +#define SQLITE_UNIX_SHM_INCR 4096 3491 + 3492 +/* 3493 +** Constants used for locking 3494 +*/ 3495 +#define UNIX_SHM_BASE 32 /* Byte offset of the first lock byte */ 3496 +#define UNIX_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */ 3497 +#define UNIX_SHM_A 0x10 /* Mask for region locks... */ 3498 +#define UNIX_SHM_B 0x20 3499 +#define UNIX_SHM_C 0x40 3500 +#define UNIX_SHM_D 0x80 3501 + 3502 +#ifdef SQLITE_DEBUG 3503 +/* 3504 +** Return a pointer to a nul-terminated string in static memory that 3505 +** describes a locking mask. The string is of the form "MSABCD" with 3506 +** each character representing a lock. "M" for MUTEX, "S" for DMS, 3507 +** and "A" through "D" for the region locks. If a lock is held, the 3508 +** letter is shown. If the lock is not held, the letter is converted 3509 +** to ".". 3510 +** 3511 +** This routine is for debugging purposes only and does not appear 3512 +** in a production build. 3513 +*/ 3514 +static const char *unixShmLockString(u8 mask){ 3515 + static char zBuf[48]; 3516 + static int iBuf = 0; 3517 + char *z; 3518 + 3519 + z = &zBuf[iBuf]; 3520 + iBuf += 8; 3521 + if( iBuf>=sizeof(zBuf) ) iBuf = 0; 3522 + 3523 + z[0] = (mask & UNIX_SHM_DMS) ? 'S' : '.'; 3524 + z[1] = (mask & UNIX_SHM_A) ? 'A' : '.'; 3525 + z[2] = (mask & UNIX_SHM_B) ? 'B' : '.'; 3526 + z[3] = (mask & UNIX_SHM_C) ? 'C' : '.'; 3527 + z[4] = (mask & UNIX_SHM_D) ? 'D' : '.'; 3528 + z[5] = 0; 3529 + return z; 3530 +} 3531 +#endif /* SQLITE_DEBUG */ 3532 + 3533 +/* 3534 +** Apply posix advisory locks for all bytes identified in lockMask. 3535 +** 3536 +** lockMask might contain multiple bits but all bits are guaranteed 3537 +** to be contiguous. 3538 +** 3539 +** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking 3540 +** otherwise. 3541 +*/ 3542 +static int unixShmSystemLock( 3543 + unixShmFile *pFile, /* Apply locks to this open shared-memory segment */ 3544 + int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ 3545 + u8 lockMask /* Which bytes to lock or unlock */ 3546 +){ 3547 + struct flock f; /* The posix advisory locking structure */ 3548 + int lockOp; /* The opcode for fcntl() */ 3549 + int i; /* Offset into the locking byte range */ 3550 + int rc; /* Result code form fcntl() */ 3551 + u8 mask; /* Mask of bits in lockMask */ 3552 + 3553 + /* Access to the unixShmFile object is serialized by the caller */ 3554 + assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); 3555 + 3556 + /* Initialize the locking parameters */ 3557 + memset(&f, 0, sizeof(f)); 3558 + f.l_type = lockType; 3559 + f.l_whence = SEEK_SET; 3560 + if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){ 3561 + lockOp = F_SETLKW; 3562 + OSTRACE(("SHM-LOCK requesting blocking lock\n")); 3563 + }else{ 3564 + lockOp = F_SETLK; 3565 + } 3566 + 3567 + /* Find the first bit in lockMask that is set */ 3568 + for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){} 3569 + assert( mask!=0 ); 3570 + f.l_start = i+UNIX_SHM_BASE; 3571 + f.l_len = 1; 3572 + 3573 + /* Extend the locking range for each additional bit that is set */ 3574 + mask <<= 1; 3575 + while( mask!=0 && (lockMask & mask)!=0 ){ 3576 + f.l_len++; 3577 + mask <<= 1; 3578 + } 3579 + 3580 + /* Verify that all bits set in lockMask are contiguous */ 3581 + assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 ); 3582 + 3583 + /* Acquire the system-level lock */ 3584 + rc = fcntl(pFile->h, lockOp, &f); 3585 + rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; 3586 + 3587 + /* Update the global lock state and do debug tracing */ 3588 +#ifdef SQLITE_DEBUG 3589 + OSTRACE(("SHM-LOCK ")); 3590 + if( rc==SQLITE_OK ){ 3591 + if( lockType==F_UNLCK ){ 3592 + OSTRACE(("unlock ok")); 3593 + pFile->exclMask &= ~lockMask; 3594 + pFile->sharedMask &= ~lockMask; 3595 + }else if( lockType==F_RDLCK ){ 3596 + OSTRACE(("read-lock ok")); 3597 + pFile->exclMask &= ~lockMask; 3598 + pFile->sharedMask |= lockMask; 3599 + }else{ 3600 + assert( lockType==F_WRLCK ); 3601 + OSTRACE(("write-lock ok")); 3602 + pFile->exclMask |= lockMask; 3603 + pFile->sharedMask &= ~lockMask; 3604 + } 3605 + }else{ 3606 + if( lockType==F_UNLCK ){ 3607 + OSTRACE(("unlock failed")); 3608 + }else if( lockType==F_RDLCK ){ 3609 + OSTRACE(("read-lock failed")); 3610 + }else{ 3611 + assert( lockType==F_WRLCK ); 3612 + OSTRACE(("write-lock failed")); 3613 + } 3614 + } 3615 + OSTRACE((" - change requested %s - afterwards %s:%s\n", 3616 + unixShmLockString(lockMask), 3617 + unixShmLockString(pFile->sharedMask), 3618 + unixShmLockString(pFile->exclMask))); 3619 +#endif 3620 + 3621 + return rc; 3622 +} 3623 + 3624 +/* 3625 +** For connection p, unlock all of the locks identified by the unlockMask 3626 +** parameter. 3627 +*/ 3628 +static int unixShmUnlock( 3629 + unixShmFile *pFile, /* The underlying shared-memory file */ 3630 + unixShm *p, /* The connection to be unlocked */ 3631 + u8 unlockMask /* Mask of locks to be unlocked */ 3632 +){ 3633 + int rc; /* Result code */ 3634 + unixShm *pX; /* For looping over all sibling connections */ 3635 + u8 allMask; /* Union of locks held by connections other than "p" */ 3636 + 3637 + /* Access to the unixShmFile object is serialized by the caller */ 3638 + assert( sqlite3_mutex_held(pFile->mutex) ); 3639 + 3640 + /* Compute locks held by sibling connections */ 3641 + allMask = 0; 3642 + for(pX=pFile->pFirst; pX; pX=pX->pNext){ 3643 + if( pX==p ) continue; 3644 + assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); 3645 + allMask |= pX->sharedMask; 3646 + } 3647 + 3648 + /* Unlock the system-level locks */ 3649 + if( (unlockMask & allMask)!=unlockMask ){ 3650 + rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask); 3651 + }else{ 3652 + rc = SQLITE_OK; 3653 + } 3654 + 3655 + /* Undo the local locks */ 3656 + if( rc==SQLITE_OK ){ 3657 + p->exclMask &= ~unlockMask; 3658 + p->sharedMask &= ~unlockMask; 3659 + } 3660 + return rc; 3661 +} 3662 + 3663 +/* 3664 +** Get reader locks for connection p on all locks in the readMask parameter. 3665 +*/ 3666 +static int unixShmSharedLock( 3667 + unixShmFile *pFile, /* The underlying shared-memory file */ 3668 + unixShm *p, /* The connection to get the shared locks */ 3669 + u8 readMask /* Mask of shared locks to be acquired */ 3670 +){ 3671 + int rc; /* Result code */ 3672 + unixShm *pX; /* For looping over all sibling connections */ 3673 + u8 allShared; /* Union of locks held by connections other than "p" */ 3674 + 3675 + /* Access to the unixShmFile object is serialized by the caller */ 3676 + assert( sqlite3_mutex_held(pFile->mutex) ); 3677 + 3678 + /* Find out which shared locks are already held by sibling connections. 3679 + ** If any sibling already holds an exclusive lock, go ahead and return 3680 + ** SQLITE_BUSY. 3681 + */ 3682 + allShared = 0; 3683 + for(pX=pFile->pFirst; pX; pX=pX->pNext){ 3684 + if( pX==p ) continue; 3685 + if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY; 3686 + allShared |= pX->sharedMask; 3687 + } 3688 + 3689 + /* Get shared locks at the system level, if necessary */ 3690 + if( (~allShared) & readMask ){ 3691 + rc = unixShmSystemLock(pFile, F_RDLCK, readMask); 3692 + }else{ 3693 + rc = SQLITE_OK; 3694 + } 3695 + 3696 + /* Get the local shared locks */ 3697 + if( rc==SQLITE_OK ){ 3698 + p->sharedMask |= readMask; 3699 + } 3700 + return rc; 3701 +} 3702 + 3703 +/* 3704 +** For connection p, get an exclusive lock on all locks identified in 3705 +** the writeMask parameter. 3706 +*/ 3707 +static int unixShmExclusiveLock( 3708 + unixShmFile *pFile, /* The underlying shared-memory file */ 3709 + unixShm *p, /* The connection to get the exclusive locks */ 3710 + u8 writeMask /* Mask of exclusive locks to be acquired */ 3711 +){ 3712 + int rc; /* Result code */ 3713 + unixShm *pX; /* For looping over all sibling connections */ 3714 + 3715 + /* Access to the unixShmFile object is serialized by the caller */ 3716 + assert( sqlite3_mutex_held(pFile->mutex) ); 3717 + 3718 + /* Make sure no sibling connections hold locks that will block this 3719 + ** lock. If any do, return SQLITE_BUSY right away. 3720 + */ 3721 + for(pX=pFile->pFirst; pX; pX=pX->pNext){ 3722 + if( pX==p ) continue; 3723 + if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY; 3724 + if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY; 3725 + } 3726 + 3727 + /* Get the exclusive locks at the system level. Then if successful 3728 + ** also mark the local connection as being locked. 3729 + */ 3730 + rc = unixShmSystemLock(pFile, F_WRLCK, writeMask); 3731 + if( rc==SQLITE_OK ){ 3732 + p->sharedMask &= ~writeMask; 3733 + p->exclMask |= writeMask; 3734 + } 3735 + return rc; 3736 +} 3737 + 3738 +/* 3739 +** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0. 3740 +** 3741 +** This is not a VFS shared-memory method; it is a utility function called 3742 +** by VFS shared-memory methods. 3743 +*/ 3744 +static void unixShmPurge(void){ 3745 + unixShmFile **pp; 3746 + unixShmFile *p; 3747 + assert( unixMutexHeld() ); 3748 + pp = &unixShmFileList; 3749 + while( (p = *pp)!=0 ){ 3750 + if( p->nRef==0 ){ 3751 + if( p->mutex ) sqlite3_mutex_free(p->mutex); 3752 + if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf); 3753 + if( p->h>=0 ) close(p->h); 3754 + *pp = p->pNext; 3755 + sqlite3_free(p); 3756 + }else{ 3757 + pp = &p->pNext; 3758 + } 3759 + } 3760 +} 3761 + 3762 +/* 3763 +** Open a shared-memory area. This particular implementation uses 3764 +** mmapped files. 3765 +** 3766 +** zName is a filename used to identify the shared-memory area. The 3767 +** implementation does not (and perhaps should not) use this name 3768 +** directly, but rather use it as a template for finding an appropriate 3769 +** name for the shared-memory storage. In this implementation, the 3770 +** string "-index" is appended to zName and used as the name of the 3771 +** mmapped file. 3772 +** 3773 +** When opening a new shared-memory file, if no other instances of that 3774 +** file are currently open, in this process or in other processes, then 3775 +** the file must be truncated to zero length or have its header cleared. 3776 +*/ 3777 +static int unixShmOpen( 3778 + sqlite3_file *fd /* The file descriptor of the associated database */ 3779 +){ 3780 + struct unixShm *p = 0; /* The connection to be opened */ 3781 + struct unixShmFile *pFile = 0; /* The underlying mmapped file */ 3782 + int rc; /* Result code */ 3783 + struct unixFileId fid; /* Unix file identifier */ 3784 + struct unixShmFile *pNew; /* Newly allocated pFile */ 3785 + struct stat sStat; /* Result from stat() an fstat() */ 3786 + struct unixFile *pDbFd; /* Underlying database file */ 3787 + int nPath; /* Size of pDbFd->zPath in bytes */ 3788 + 3789 + /* Allocate space for the new sqlite3_shm object. Also speculatively 3790 + ** allocate space for a new unixShmFile and filename. 3791 + */ 3792 + p = sqlite3_malloc( sizeof(*p) ); 3793 + if( p==0 ) return SQLITE_NOMEM; 3794 + memset(p, 0, sizeof(*p)); 3795 + pDbFd = (struct unixFile*)fd; 3796 + assert( pDbFd->pShm==0 ); 3797 + nPath = strlen(pDbFd->zPath); 3798 + pNew = sqlite3_malloc( sizeof(*pFile) + nPath + 15 ); 3799 + if( pNew==0 ){ 3800 + sqlite3_free(p); 3801 + return SQLITE_NOMEM; 3802 + } 3803 + memset(pNew, 0, sizeof(*pNew)); 3804 + pNew->zFilename = (char*)&pNew[1]; 3805 + sqlite3_snprintf(nPath+15, pNew->zFilename, "%s-wal-index", pDbFd->zPath); 3806 + 3807 + /* Look to see if there is an existing unixShmFile that can be used. 3808 + ** If no matching unixShmFile currently exists, create a new one. 3809 + */ 3810 + unixEnterMutex(); 3811 + rc = stat(pNew->zFilename, &sStat); 3812 + if( rc==0 ){ 3813 + memset(&fid, 0, sizeof(fid)); 3814 + fid.dev = sStat.st_dev; 3815 + fid.ino = sStat.st_ino; 3816 + for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){ 3817 + if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break; 3818 + } 3819 + } 3820 + if( pFile ){ 3821 + sqlite3_free(pNew); 3822 + }else{ 3823 + pFile = pNew; 3824 + pNew = 0; 3825 + pFile->h = -1; 3826 + pFile->pNext = unixShmFileList; 3827 + unixShmFileList = pFile; 3828 + 3829 + pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 3830 + if( pFile->mutex==0 ){ 3831 + rc = SQLITE_NOMEM; 3832 + goto shm_open_err; 3833 + } 3834 + pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 3835 + if( pFile->mutexBuf==0 ){ 3836 + rc = SQLITE_NOMEM; 3837 + goto shm_open_err; 3838 + } 3839 + 3840 + pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664); 3841 + if( pFile->h<0 ){ 3842 + rc = SQLITE_CANTOPEN_BKPT; 3843 + goto shm_open_err; 3844 + } 3845 + 3846 + rc = fstat(pFile->h, &sStat); 3847 + if( rc ){ 3848 + rc = SQLITE_CANTOPEN_BKPT; 3849 + goto shm_open_err; 3850 + } 3851 + pFile->fid.dev = sStat.st_dev; 3852 + pFile->fid.ino = sStat.st_ino; 3853 + 3854 + /* Check to see if another process is holding the dead-man switch. 3855 + ** If not, truncate the file to zero length. 3856 + */ 3857 + if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){ 3858 + if( ftruncate(pFile->h, 0) ){ 3859 + rc = SQLITE_IOERR; 3860 + } 3861 + } 3862 + if( rc==SQLITE_OK ){ 3863 + rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS); 3864 + } 3865 + if( rc ) goto shm_open_err; 3866 + } 3867 + 3868 + /* Make the new connection a child of the unixShmFile */ 3869 + p->pFile = pFile; 3870 + p->pNext = pFile->pFirst; 3871 +#ifdef SQLITE_DEBUG 3872 + p->id = pFile->nextShmId++; 3873 +#endif 3874 + pFile->pFirst = p; 3875 + pFile->nRef++; 3876 + pDbFd->pShm = p; 3877 + unixLeaveMutex(); 3878 + return SQLITE_OK; 3879 + 3880 + /* Jump here on any error */ 3881 +shm_open_err: 3882 + unixShmPurge(); /* This call frees pFile if required */ 3883 + sqlite3_free(p); 3884 + sqlite3_free(pNew); 3885 + unixLeaveMutex(); 3886 + return rc; 3887 +} 3888 + 3889 +/* 3890 +** Close a connection to shared-memory. Delete the underlying 3891 +** storage if deleteFlag is true. 3892 +*/ 3893 +static int unixShmClose( 3894 + sqlite3_file *fd, /* The underlying database file */ 3895 + int deleteFlag /* Delete shared-memory if true */ 3896 +){ 3897 + unixShm *p; /* The connection to be closed */ 3898 + unixShmFile *pFile; /* The underlying shared-memory file */ 3899 + unixShm **pp; /* For looping over sibling connections */ 3900 + unixFile *pDbFd; /* The underlying database file */ 3901 + 3902 + pDbFd = (unixFile*)fd; 3903 + p = pDbFd->pShm; 3904 + if( p==0 ) return SQLITE_OK; 3905 + pFile = p->pFile; 3906 + 3907 + /* Verify that the connection being closed holds no locks */ 3908 + assert( p->exclMask==0 ); 3909 + assert( p->sharedMask==0 ); 3910 + 3911 + /* Remove connection p from the set of connections associated with pFile */ 3912 + sqlite3_mutex_enter(pFile->mutex); 3913 + for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} 3914 + *pp = p->pNext; 3915 + 3916 + /* Free the connection p */ 3917 + sqlite3_free(p); 3918 + pDbFd->pShm = 0; 3919 + sqlite3_mutex_leave(pFile->mutex); 3920 + 3921 + /* If pFile->nRef has reached 0, then close the underlying 3922 + ** shared-memory file, too */ 3923 + unixEnterMutex(); 3924 + assert( pFile->nRef>0 ); 3925 + pFile->nRef--; 3926 + if( pFile->nRef==0 ){ 3927 + if( deleteFlag ) unlink(pFile->zFilename); 3928 + unixShmPurge(); 3929 + } 3930 + unixLeaveMutex(); 3931 + 3932 + return SQLITE_OK; 3933 +} 3934 + 3935 +/* 3936 +** Query and/or changes the size of the underlying storage for 3937 +** a shared-memory segment. The reqSize parameter is the new size 3938 +** of the underlying storage, or -1 to do just a query. The size 3939 +** of the underlying storage (after resizing if resizing occurs) is 3940 +** written into pNewSize. 3941 +** 3942 +** This routine does not (necessarily) change the size of the mapping 3943 +** of the underlying storage into memory. Use xShmGet() to change 3944 +** the mapping size. 3945 +** 3946 +** The reqSize parameter is the minimum size requested. The implementation 3947 +** is free to expand the storage to some larger amount if it chooses. 3948 +*/ 3949 +static int unixShmSize( 3950 + sqlite3_file *fd, /* The open database file holding SHM */ 3951 + int reqSize, /* Requested size. -1 for query only */ 3952 + int *pNewSize /* Write new size here */ 3953 +){ 3954 + unixFile *pDbFd = (unixFile*)fd; 3955 + unixShm *p = pDbFd->pShm; 3956 + unixShmFile *pFile = p->pFile; 3957 + int rc = SQLITE_OK; 3958 + struct stat sStat; 3959 + 3960 + /* On a query, this loop runs once. When reqSize>=0, the loop potentially 3961 + ** runs twice, except if the actual size is already greater than or equal 3962 + ** to the requested size, reqSize is set to -1 on the first iteration and 3963 + ** the loop only runs once. 3964 + */ 3965 + while( 1 ){ 3966 + if( fstat(pFile->h, &sStat)==0 ){ 3967 + *pNewSize = (int)sStat.st_size; 3968 + if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break; 3969 + }else{ 3970 + *pNewSize = 0; 3971 + rc = SQLITE_IOERR; 3972 + break; 3973 + } 3974 + if( reqSize<0 ) break; 3975 + reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR; 3976 + reqSize *= SQLITE_UNIX_SHM_INCR; 3977 + rc = ftruncate(pFile->h, reqSize); 3978 + reqSize = -1; 3979 + } 3980 + return rc; 3981 +} 3982 + 3983 + 3984 +/* 3985 +** Map the shared storage into memory. The minimum size of the 3986 +** mapping should be reqMapSize if reqMapSize is positive. If 3987 +** reqMapSize is zero or negative, the implementation can choose 3988 +** whatever mapping size is convenient. 3989 +** 3990 +** *ppBuf is made to point to the memory which is a mapping of the 3991 +** underlying storage. A mutex is acquired to prevent other threads 3992 +** from running while *ppBuf is in use in order to prevent other threads 3993 +** remapping *ppBuf out from under this thread. The unixShmRelease() 3994 +** call will release the mutex. However, if the lock state is CHECKPOINT, 3995 +** the mutex is not acquired because CHECKPOINT will never remap the 3996 +** buffer. RECOVER might remap, though, so CHECKPOINT will acquire 3997 +** the mutex if and when it promotes to RECOVER. 3998 +** 3999 +** RECOVER needs to be atomic. The same mutex that prevents *ppBuf from 4000 +** being remapped also prevents more than one thread from being in 4001 +** RECOVER at a time. But, RECOVER sometimes wants to remap itself. 4002 +** To prevent RECOVER from losing its lock while remapping, the 4003 +** mutex is not released by unixShmRelease() when in RECOVER. 4004 +** 4005 +** *pNewMapSize is set to the size of the mapping. 4006 +** 4007 +** *ppBuf and *pNewMapSize might be NULL and zero if no space has 4008 +** yet been allocated to the underlying storage. 4009 +*/ 4010 +static int unixShmGet( 4011 + sqlite3_file *fd, /* Database file holding shared memory */ 4012 + int reqMapSize, /* Requested size of mapping. -1 means don't care */ 4013 + int *pNewMapSize, /* Write new size of mapping here */ 4014 + void **ppBuf /* Write mapping buffer origin here */ 4015 +){ 4016 + unixFile *pDbFd = (unixFile*)fd; 4017 + unixShm *p = pDbFd->pShm; 4018 + unixShmFile *pFile = p->pFile; 4019 + int rc = SQLITE_OK; 4020 + 4021 + if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){ 4022 + assert( sqlite3_mutex_notheld(pFile->mutex) ); 4023 + sqlite3_mutex_enter(pFile->mutexBuf); 4024 + p->hasMutexBuf = 1; 4025 + } 4026 + sqlite3_mutex_enter(pFile->mutex); 4027 + if( pFile->szMap==0 || reqMapSize>pFile->szMap ){ 4028 + int actualSize; 4029 + if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK 4030 + && reqMapSize<actualSize 4031 + ){ 4032 + reqMapSize = actualSize; 4033 + } 4034 + if( pFile->pMMapBuf ){ 4035 + munmap(pFile->pMMapBuf, pFile->szMap); 4036 + } 4037 + pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED, 4038 + pFile->h, 0); 4039 + pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0; 4040 + } 4041 + *pNewMapSize = pFile->szMap; 4042 + *ppBuf = pFile->pMMapBuf; 4043 + sqlite3_mutex_leave(pFile->mutex); 4044 + return rc; 4045 +} 4046 + 4047 +/* 4048 +** Release the lock held on the shared memory segment to that other 4049 +** threads are free to resize it if necessary. 4050 +** 4051 +** If the lock is not currently held, this routine is a harmless no-op. 4052 +** 4053 +** If the shared-memory object is in lock state RECOVER, then we do not 4054 +** really want to release the lock, so in that case too, this routine 4055 +** is a no-op. 4056 +*/ 4057 +static int unixShmRelease(sqlite3_file *fd){ 4058 + unixFile *pDbFd = (unixFile*)fd; 4059 + unixShm *p = pDbFd->pShm; 4060 + 4061 + if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){ 4062 + assert( sqlite3_mutex_notheld(p->pFile->mutex) ); 4063 + sqlite3_mutex_leave(p->pFile->mutexBuf); 4064 + p->hasMutexBuf = 0; 4065 + } 4066 + return SQLITE_OK; 4067 +} 4068 + 4069 +/* 4070 +** Symbolic names for LOCK states used for debugging. 4071 +*/ 4072 +#ifdef SQLITE_DEBUG 4073 +static const char *azLkName[] = { 4074 + "UNLOCK", 4075 + "READ", 4076 + "READ_FULL", 4077 + "WRITE", 4078 + "PENDING", 4079 + "CHECKPOINT", 4080 + "RECOVER" 4081 +}; 4082 +#endif 4083 + 4084 + 4085 +/* 4086 +** Change the lock state for a shared-memory segment. 4087 +*/ 4088 +static int unixShmLock( 4089 + sqlite3_file *fd, /* Database file holding the shared memory */ 4090 + int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */ 4091 + int *pGotLock /* The lock you actually got */ 4092 +){ 4093 + unixFile *pDbFd = (unixFile*)fd; 4094 + unixShm *p = pDbFd->pShm; 4095 + unixShmFile *pFile = p->pFile; 4096 + int rc = SQLITE_PROTOCOL; 4097 + 4098 + /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never 4099 + ** directly requested; they are side effects from requesting 4100 + ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively. 4101 + */ 4102 + assert( desiredLock==SQLITE_SHM_UNLOCK 4103 + || desiredLock==SQLITE_SHM_READ 4104 + || desiredLock==SQLITE_SHM_WRITE 4105 + || desiredLock==SQLITE_SHM_CHECKPOINT 4106 + || desiredLock==SQLITE_SHM_RECOVER ); 4107 + 4108 + /* Return directly if this is just a lock state query, or if 4109 + ** the connection is already in the desired locking state. 4110 + */ 4111 + if( desiredLock==p->lockState 4112 + || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL) 4113 + ){ 4114 + OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n", 4115 + p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState])); 4116 + if( pGotLock ) *pGotLock = p->lockState; 4117 + return SQLITE_OK; 4118 + } 4119 + 4120 + OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n", 4121 + p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock])); 4122 + 4123 + if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){ 4124 + assert( sqlite3_mutex_notheld(pFile->mutex) ); 4125 + sqlite3_mutex_enter(pFile->mutexBuf); 4126 + p->hasMutexBuf = 1; 4127 + } 4128 + sqlite3_mutex_enter(pFile->mutex); 4129 + switch( desiredLock ){ 4130 + case SQLITE_SHM_UNLOCK: { 4131 + assert( p->lockState!=SQLITE_SHM_RECOVER ); 4132 + unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D); 4133 + rc = SQLITE_OK; 4134 + p->lockState = SQLITE_SHM_UNLOCK; 4135 + break; 4136 + } 4137 + case SQLITE_SHM_READ: { 4138 + if( p->lockState==SQLITE_SHM_UNLOCK ){ 4139 + int nAttempt; 4140 + rc = SQLITE_BUSY; 4141 + assert( p->lockState==SQLITE_SHM_UNLOCK ); 4142 + for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){ 4143 + rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B); 4144 + if( rc==SQLITE_BUSY ){ 4145 + rc = unixShmSharedLock(pFile, p, UNIX_SHM_D); 4146 + if( rc==SQLITE_OK ){ 4147 + p->lockState = SQLITE_SHM_READ_FULL; 4148 + } 4149 + }else{ 4150 + unixShmUnlock(pFile, p, UNIX_SHM_B); 4151 + p->lockState = SQLITE_SHM_READ; 4152 + } 4153 + } 4154 + }else{ 4155 + assert( p->lockState==SQLITE_SHM_WRITE 4156 + || p->lockState==SQLITE_SHM_RECOVER ); 4157 + rc = unixShmSharedLock(pFile, p, UNIX_SHM_A); 4158 + unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D); 4159 + p->lockState = SQLITE_SHM_READ; 4160 + } 4161 + break; 4162 + } 4163 + case SQLITE_SHM_WRITE: { 4164 + assert( p->lockState==SQLITE_SHM_READ 4165 + || p->lockState==SQLITE_SHM_READ_FULL ); 4166 + rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D); 4167 + if( rc==SQLITE_OK ){ 4168 + p->lockState = SQLITE_SHM_WRITE; 4169 + } 4170 + break; 4171 + } 4172 + case SQLITE_SHM_CHECKPOINT: { 4173 + assert( p->lockState==SQLITE_SHM_UNLOCK 4174 + || p->lockState==SQLITE_SHM_PENDING 4175 + ); 4176 + if( p->lockState==SQLITE_SHM_UNLOCK ){ 4177 + rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C); 4178 + if( rc==SQLITE_OK ){ 4179 + p->lockState = SQLITE_SHM_PENDING; 4180 + } 4181 + } 4182 + if( p->lockState==SQLITE_SHM_PENDING ){ 4183 + rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A); 4184 + if( rc==SQLITE_OK ){ 4185 + p->lockState = SQLITE_SHM_CHECKPOINT; 4186 + } 4187 + } 4188 + break; 4189 + } 4190 + default: { 4191 + assert( desiredLock==SQLITE_SHM_RECOVER ); 4192 + assert( p->lockState==SQLITE_SHM_READ 4193 + || p->lockState==SQLITE_SHM_READ_FULL 4194 + ); 4195 + assert( sqlite3_mutex_held(pFile->mutexBuf) ); 4196 + rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C); 4197 + if( rc==SQLITE_OK ){ 4198 + p->lockState = SQLITE_SHM_RECOVER; 4199 + } 4200 + break; 4201 + } 4202 + } 4203 + sqlite3_mutex_leave(pFile->mutex); 4204 + OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n", 4205 + p->id, getpid(), azLkName[p->lockState])); 4206 + if( pGotLock ) *pGotLock = p->lockState; 4207 + return rc; 4208 +} 4209 + 4210 +#else 4211 +# define unixShmOpen 0 4212 +# define unixShmSize 0 4213 +# define unixShmGet 0 4214 +# define unixShmRelease 0 4215 +# define unixShmLock 0 4216 +# define unixShmClose 0 4217 +#endif /* #ifndef SQLITE_OMIT_WAL */ 4218 + 3403 4219 /* 3404 4220 ** Here ends the implementation of all sqlite3_file methods. 3405 4221 ** 3406 4222 ********************** End sqlite3_file Methods ******************************* 3407 4223 ******************************************************************************/ 3408 4224 3409 4225 /* ................................................................................ 3436 4252 ** 3437 4253 ** * A constant sqlite3_io_methods object call METHOD that has locking 3438 4254 ** methods CLOSE, LOCK, UNLOCK, CKRESLOCK. 3439 4255 ** 3440 4256 ** * An I/O method finder function called FINDER that returns a pointer 3441 4257 ** to the METHOD object in the previous bullet. 3442 4258 */ 3443 -#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \ 4259 +#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK) \ 3444 4260 static const sqlite3_io_methods METHOD = { \ 3445 - 1, /* iVersion */ \ 4261 + VERSION, /* iVersion */ \ 3446 4262 CLOSE, /* xClose */ \ 3447 4263 unixRead, /* xRead */ \ 3448 4264 unixWrite, /* xWrite */ \ 3449 4265 unixTruncate, /* xTruncate */ \ 3450 4266 unixSync, /* xSync */ \ 3451 4267 unixFileSize, /* xFileSize */ \ 3452 4268 LOCK, /* xLock */ \ 3453 4269 UNLOCK, /* xUnlock */ \ 3454 4270 CKLOCK, /* xCheckReservedLock */ \ 3455 4271 unixFileControl, /* xFileControl */ \ 3456 4272 unixSectorSize, /* xSectorSize */ \ 3457 - unixDeviceCharacteristics /* xDeviceCapabilities */ \ 4273 + unixDeviceCharacteristics, /* xDeviceCapabilities */ \ 4274 + unixShmOpen, /* xShmOpen */ \ 4275 + unixShmSize, /* xShmSize */ \ 4276 + unixShmGet, /* xShmGet */ \ 4277 + unixShmRelease, /* xShmRelease */ \ 4278 + unixShmLock, /* xShmLock */ \ 4279 + unixShmClose /* xShmClose */ \ 3458 4280 }; \ 3459 4281 static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \ 3460 4282 UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \ 3461 4283 return &METHOD; \ 3462 4284 } \ 3463 4285 static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \ 3464 4286 = FINDER##Impl; ................................................................................ 3467 4289 ** Here are all of the sqlite3_io_methods objects for each of the 3468 4290 ** locking strategies. Functions that return pointers to these methods 3469 4291 ** are also created. 3470 4292 */ 3471 4293 IOMETHODS( 3472 4294 posixIoFinder, /* Finder function name */ 3473 4295 posixIoMethods, /* sqlite3_io_methods object name */ 4296 + 2, /* ShmOpen is enabled */ 3474 4297 unixClose, /* xClose method */ 3475 4298 unixLock, /* xLock method */ 3476 4299 unixUnlock, /* xUnlock method */ 3477 4300 unixCheckReservedLock /* xCheckReservedLock method */ 3478 4301 ) 3479 4302 IOMETHODS( 3480 4303 nolockIoFinder, /* Finder function name */ 3481 4304 nolockIoMethods, /* sqlite3_io_methods object name */ 4305 + 1, /* ShmOpen is disabled */ 3482 4306 nolockClose, /* xClose method */ 3483 4307 nolockLock, /* xLock method */ 3484 4308 nolockUnlock, /* xUnlock method */ 3485 4309 nolockCheckReservedLock /* xCheckReservedLock method */ 3486 4310 ) 3487 4311 IOMETHODS( 3488 4312 dotlockIoFinder, /* Finder function name */ 3489 4313 dotlockIoMethods, /* sqlite3_io_methods object name */ 4314 + 1, /* ShmOpen is disabled */ 3490 4315 dotlockClose, /* xClose method */ 3491 4316 dotlockLock, /* xLock method */ 3492 4317 dotlockUnlock, /* xUnlock method */ 3493 4318 dotlockCheckReservedLock /* xCheckReservedLock method */ 3494 4319 ) 3495 4320 3496 4321 #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS 3497 4322 IOMETHODS( 3498 4323 flockIoFinder, /* Finder function name */ 3499 4324 flockIoMethods, /* sqlite3_io_methods object name */ 4325 + 1, /* ShmOpen is disabled */ 3500 4326 flockClose, /* xClose method */ 3501 4327 flockLock, /* xLock method */ 3502 4328 flockUnlock, /* xUnlock method */ 3503 4329 flockCheckReservedLock /* xCheckReservedLock method */ 3504 4330 ) 3505 4331 #endif 3506 4332 3507 4333 #if OS_VXWORKS 3508 4334 IOMETHODS( 3509 4335 semIoFinder, /* Finder function name */ 3510 4336 semIoMethods, /* sqlite3_io_methods object name */ 4337 + 1, /* ShmOpen is disabled */ 3511 4338 semClose, /* xClose method */ 3512 4339 semLock, /* xLock method */ 3513 4340 semUnlock, /* xUnlock method */ 3514 4341 semCheckReservedLock /* xCheckReservedLock method */ 3515 4342 ) 3516 4343 #endif 3517 4344 3518 4345 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 3519 4346 IOMETHODS( 3520 4347 afpIoFinder, /* Finder function name */ 3521 4348 afpIoMethods, /* sqlite3_io_methods object name */ 4349 + 1, /* ShmOpen is disabled */ 3522 4350 afpClose, /* xClose method */ 3523 4351 afpLock, /* xLock method */ 3524 4352 afpUnlock, /* xUnlock method */ 3525 4353 afpCheckReservedLock /* xCheckReservedLock method */ 3526 4354 ) 3527 4355 #endif 3528 4356 ................................................................................ 3539 4367 static int proxyClose(sqlite3_file*); 3540 4368 static int proxyLock(sqlite3_file*, int); 3541 4369 static int proxyUnlock(sqlite3_file*, int); 3542 4370 static int proxyCheckReservedLock(sqlite3_file*, int*); 3543 4371 IOMETHODS( 3544 4372 proxyIoFinder, /* Finder function name */ 3545 4373 proxyIoMethods, /* sqlite3_io_methods object name */ 4374 + 1, /* ShmOpen is disabled */ 3546 4375 proxyClose, /* xClose method */ 3547 4376 proxyLock, /* xLock method */ 3548 4377 proxyUnlock, /* xUnlock method */ 3549 4378 proxyCheckReservedLock /* xCheckReservedLock method */ 3550 4379 ) 3551 4380 #endif 3552 4381 3553 4382 /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */ 3554 4383 #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE 3555 4384 IOMETHODS( 3556 4385 nfsIoFinder, /* Finder function name */ 3557 4386 nfsIoMethods, /* sqlite3_io_methods object name */ 4387 + 1, /* ShmOpen is disabled */ 3558 4388 unixClose, /* xClose method */ 3559 4389 unixLock, /* xLock method */ 3560 4390 nfsUnlock, /* xUnlock method */ 3561 4391 unixCheckReservedLock /* xCheckReservedLock method */ 3562 4392 ) 3563 4393 #endif 3564 4394 ................................................................................ 3704 4534 UNUSED_PARAMETER(isDelete); 3705 4535 3706 4536 OSTRACE3("OPEN %-3d %s\n", h, zFilename); 3707 4537 pNew->h = h; 3708 4538 pNew->dirfd = dirfd; 3709 4539 SET_THREADID(pNew); 3710 4540 pNew->fileFlags = 0; 4541 + assert( zFilename==0 || zFilename[0]=='/' ); /* Never a relative pathname */ 4542 + pNew->zPath = zFilename; 3711 4543 3712 4544 #if OS_VXWORKS 3713 4545 pNew->pId = vxworksFindFileId(zFilename); 3714 4546 if( pNew->pId==0 ){ 3715 4547 noLock = 1; 3716 4548 rc = SQLITE_NOMEM; 3717 4549 } ................................................................................ 4571 5403 static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ 4572 5404 UNUSED_PARAMETER(NotUsed); 4573 5405 UNUSED_PARAMETER(NotUsed2); 4574 5406 UNUSED_PARAMETER(NotUsed3); 4575 5407 return 0; 4576 5408 } 4577 5409 4578 -#ifndef SQLITE_OMIT_WAL 4579 - 4580 -/* Forward reference */ 4581 -typedef struct unixShm unixShm; 4582 -typedef struct unixShmFile unixShmFile; 4583 - 4584 -/* 4585 -** Object used to represent a single file opened and mmapped to provide 4586 -** shared memory. When multiple threads all reference the same 4587 -** log-summary, each thread has its own unixFile object, but they all 4588 -** point to a single instance of this object. In other words, each 4589 -** log-summary is opened only once per process. 4590 -** 4591 -** unixMutexHeld() must be true when creating or destroying 4592 -** this object or while reading or writing the following fields: 4593 -** 4594 -** nRef 4595 -** pNext 4596 -** 4597 -** The following fields are read-only after the object is created: 4598 -** 4599 -** fid 4600 -** zFilename 4601 -** 4602 -** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and 4603 -** unixMutexHeld() is true when reading or writing any other field 4604 -** in this structure. 4605 -** 4606 -** To avoid deadlocks, mutex and mutexBuf are always released in the 4607 -** reverse order that they are acquired. mutexBuf is always acquired 4608 -** first and released last. This invariant is check by asserting 4609 -** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or 4610 -** released. 4611 -*/ 4612 -struct unixShmFile { 4613 - struct unixFileId fid; /* Unique file identifier */ 4614 - sqlite3_mutex *mutex; /* Mutex to access this object */ 4615 - sqlite3_mutex *mutexBuf; /* Mutex to access zBuf[] */ 4616 - char *zFilename; /* Name of the file */ 4617 - int h; /* Open file descriptor */ 4618 - int szMap; /* Size of the mapping of file into memory */ 4619 - char *pMMapBuf; /* Where currently mmapped(). NULL if unmapped */ 4620 - int nRef; /* Number of unixShm objects pointing to this */ 4621 - unixShm *pFirst; /* All unixShm objects pointing to this */ 4622 - unixShmFile *pNext; /* Next in list of all unixShmFile objects */ 4623 -#ifdef SQLITE_DEBUG 4624 - u8 exclMask; /* Mask of exclusive locks held */ 4625 - u8 sharedMask; /* Mask of shared locks held */ 4626 - u8 nextShmId; /* Next available unixShm.id value */ 4627 -#endif 4628 -}; 4629 - 4630 -/* 4631 -** A global array of all unixShmFile objects. 4632 -** 4633 -** The unixMutexHeld() must be true while reading or writing this list. 4634 -*/ 4635 -static unixShmFile *unixShmFileList = 0; 4636 - 4637 -/* 4638 -** Structure used internally by this VFS to record the state of an 4639 -** open shared memory connection. 4640 -** 4641 -** unixShm.pFile->mutex must be held while reading or writing the 4642 -** unixShm.pNext and unixShm.locks[] elements. 4643 -** 4644 -** The unixShm.pFile element is initialized when the object is created 4645 -** and is read-only thereafter. 4646 -*/ 4647 -struct unixShm { 4648 - unixShmFile *pFile; /* The underlying unixShmFile object */ 4649 - unixShm *pNext; /* Next unixShm with the same unixShmFile */ 4650 - u8 lockState; /* Current lock state */ 4651 - u8 hasMutex; /* True if holding the unixShmFile mutex */ 4652 - u8 hasMutexBuf; /* True if holding pFile->mutexBuf */ 4653 - u8 sharedMask; /* Mask of shared locks held */ 4654 - u8 exclMask; /* Mask of exclusive locks held */ 4655 -#ifdef SQLITE_DEBUG 4656 - u8 id; /* Id of this connection with its unixShmFile */ 4657 -#endif 4658 -}; 4659 - 4660 -/* 4661 -** Size increment by which shared memory grows 4662 -*/ 4663 -#define SQLITE_UNIX_SHM_INCR 4096 4664 - 4665 -/* 4666 -** Constants used for locking 4667 -*/ 4668 -#define UNIX_SHM_BASE 32 /* Byte offset of the first lock byte */ 4669 -#define UNIX_SHM_DMS 0x01 /* Mask for Dead-Man-Switch lock */ 4670 -#define UNIX_SHM_A 0x10 /* Mask for region locks... */ 4671 -#define UNIX_SHM_B 0x20 4672 -#define UNIX_SHM_C 0x40 4673 -#define UNIX_SHM_D 0x80 4674 - 4675 -#ifdef SQLITE_DEBUG 4676 -/* 4677 -** Return a pointer to a nul-terminated string in static memory that 4678 -** describes a locking mask. The string is of the form "MSABCD" with 4679 -** each character representing a lock. "M" for MUTEX, "S" for DMS, 4680 -** and "A" through "D" for the region locks. If a lock is held, the 4681 -** letter is shown. If the lock is not held, the letter is converted 4682 -** to ".". 4683 -** 4684 -** This routine is for debugging purposes only and does not appear 4685 -** in a production build. 4686 -*/ 4687 -static const char *unixShmLockString(u8 mask){ 4688 - static char zBuf[48]; 4689 - static int iBuf = 0; 4690 - char *z; 4691 - 4692 - z = &zBuf[iBuf]; 4693 - iBuf += 8; 4694 - if( iBuf>=sizeof(zBuf) ) iBuf = 0; 4695 - 4696 - z[0] = (mask & UNIX_SHM_DMS) ? 'S' : '.'; 4697 - z[1] = (mask & UNIX_SHM_A) ? 'A' : '.'; 4698 - z[2] = (mask & UNIX_SHM_B) ? 'B' : '.'; 4699 - z[3] = (mask & UNIX_SHM_C) ? 'C' : '.'; 4700 - z[4] = (mask & UNIX_SHM_D) ? 'D' : '.'; 4701 - z[5] = 0; 4702 - return z; 4703 -} 4704 -#endif /* SQLITE_DEBUG */ 4705 - 4706 -/* 4707 -** Apply posix advisory locks for all bytes identified in lockMask. 4708 -** 4709 -** lockMask might contain multiple bits but all bits are guaranteed 4710 -** to be contiguous. 4711 -** 4712 -** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking 4713 -** otherwise. 4714 -*/ 4715 -static int unixShmSystemLock( 4716 - unixShmFile *pFile, /* Apply locks to this open shared-memory segment */ 4717 - int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */ 4718 - u8 lockMask /* Which bytes to lock or unlock */ 4719 -){ 4720 - struct flock f; /* The posix advisory locking structure */ 4721 - int lockOp; /* The opcode for fcntl() */ 4722 - int i; /* Offset into the locking byte range */ 4723 - int rc; /* Result code form fcntl() */ 4724 - u8 mask; /* Mask of bits in lockMask */ 4725 - 4726 - /* Access to the unixShmFile object is serialized by the caller */ 4727 - assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); 4728 - 4729 - /* Initialize the locking parameters */ 4730 - memset(&f, 0, sizeof(f)); 4731 - f.l_type = lockType; 4732 - f.l_whence = SEEK_SET; 4733 - if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){ 4734 - lockOp = F_SETLKW; 4735 - OSTRACE(("SHM-LOCK requesting blocking lock\n")); 4736 - }else{ 4737 - lockOp = F_SETLK; 4738 - } 4739 - 4740 - /* Find the first bit in lockMask that is set */ 4741 - for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){} 4742 - assert( mask!=0 ); 4743 - f.l_start = i+UNIX_SHM_BASE; 4744 - f.l_len = 1; 4745 - 4746 - /* Extend the locking range for each additional bit that is set */ 4747 - mask <<= 1; 4748 - while( mask!=0 && (lockMask & mask)!=0 ){ 4749 - f.l_len++; 4750 - mask <<= 1; 4751 - } 4752 - 4753 - /* Verify that all bits set in lockMask are contiguous */ 4754 - assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 ); 4755 - 4756 - /* Acquire the system-level lock */ 4757 - rc = fcntl(pFile->h, lockOp, &f); 4758 - rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; 4759 - 4760 - /* Update the global lock state and do debug tracing */ 4761 -#ifdef SQLITE_DEBUG 4762 - OSTRACE(("SHM-LOCK ")); 4763 - if( rc==SQLITE_OK ){ 4764 - if( lockType==F_UNLCK ){ 4765 - OSTRACE(("unlock ok")); 4766 - pFile->exclMask &= ~lockMask; 4767 - pFile->sharedMask &= ~lockMask; 4768 - }else if( lockType==F_RDLCK ){ 4769 - OSTRACE(("read-lock ok")); 4770 - pFile->exclMask &= ~lockMask; 4771 - pFile->sharedMask |= lockMask; 4772 - }else{ 4773 - assert( lockType==F_WRLCK ); 4774 - OSTRACE(("write-lock ok")); 4775 - pFile->exclMask |= lockMask; 4776 - pFile->sharedMask &= ~lockMask; 4777 - } 4778 - }else{ 4779 - if( lockType==F_UNLCK ){ 4780 - OSTRACE(("unlock failed")); 4781 - }else if( lockType==F_RDLCK ){ 4782 - OSTRACE(("read-lock failed")); 4783 - }else{ 4784 - assert( lockType==F_WRLCK ); 4785 - OSTRACE(("write-lock failed")); 4786 - } 4787 - } 4788 - OSTRACE((" - change requested %s - afterwards %s:%s\n", 4789 - unixShmLockString(lockMask), 4790 - unixShmLockString(pFile->sharedMask), 4791 - unixShmLockString(pFile->exclMask))); 4792 -#endif 4793 - 4794 - return rc; 4795 -} 4796 - 4797 -/* 4798 -** For connection p, unlock all of the locks identified by the unlockMask 4799 -** parameter. 4800 -*/ 4801 -static int unixShmUnlock( 4802 - unixShmFile *pFile, /* The underlying shared-memory file */ 4803 - unixShm *p, /* The connection to be unlocked */ 4804 - u8 unlockMask /* Mask of locks to be unlocked */ 4805 -){ 4806 - int rc; /* Result code */ 4807 - unixShm *pX; /* For looping over all sibling connections */ 4808 - u8 allMask; /* Union of locks held by connections other than "p" */ 4809 - 4810 - /* Access to the unixShmFile object is serialized by the caller */ 4811 - assert( sqlite3_mutex_held(pFile->mutex) ); 4812 - 4813 - /* Compute locks held by sibling connections */ 4814 - allMask = 0; 4815 - for(pX=pFile->pFirst; pX; pX=pX->pNext){ 4816 - if( pX==p ) continue; 4817 - assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); 4818 - allMask |= pX->sharedMask; 4819 - } 4820 - 4821 - /* Unlock the system-level locks */ 4822 - if( (unlockMask & allMask)!=unlockMask ){ 4823 - rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask); 4824 - }else{ 4825 - rc = SQLITE_OK; 4826 - } 4827 - 4828 - /* Undo the local locks */ 4829 - if( rc==SQLITE_OK ){ 4830 - p->exclMask &= ~unlockMask; 4831 - p->sharedMask &= ~unlockMask; 4832 - } 4833 - return rc; 4834 -} 4835 - 4836 -/* 4837 -** Get reader locks for connection p on all locks in the readMask parameter. 4838 -*/ 4839 -static int unixShmSharedLock( 4840 - unixShmFile *pFile, /* The underlying shared-memory file */ 4841 - unixShm *p, /* The connection to get the shared locks */ 4842 - u8 readMask /* Mask of shared locks to be acquired */ 4843 -){ 4844 - int rc; /* Result code */ 4845 - unixShm *pX; /* For looping over all sibling connections */ 4846 - u8 allShared; /* Union of locks held by connections other than "p" */ 4847 - 4848 - /* Access to the unixShmFile object is serialized by the caller */ 4849 - assert( sqlite3_mutex_held(pFile->mutex) ); 4850 - 4851 - /* Find out which shared locks are already held by sibling connections. 4852 - ** If any sibling already holds an exclusive lock, go ahead and return 4853 - ** SQLITE_BUSY. 4854 - */ 4855 - allShared = 0; 4856 - for(pX=pFile->pFirst; pX; pX=pX->pNext){ 4857 - if( pX==p ) continue; 4858 - if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY; 4859 - allShared |= pX->sharedMask; 4860 - } 4861 - 4862 - /* Get shared locks at the system level, if necessary */ 4863 - if( (~allShared) & readMask ){ 4864 - rc = unixShmSystemLock(pFile, F_RDLCK, readMask); 4865 - }else{ 4866 - rc = SQLITE_OK; 4867 - } 4868 - 4869 - /* Get the local shared locks */ 4870 - if( rc==SQLITE_OK ){ 4871 - p->sharedMask |= readMask; 4872 - } 4873 - return rc; 4874 -} 4875 - 4876 -/* 4877 -** For connection p, get an exclusive lock on all locks identified in 4878 -** the writeMask parameter. 4879 -*/ 4880 -static int unixShmExclusiveLock( 4881 - unixShmFile *pFile, /* The underlying shared-memory file */ 4882 - unixShm *p, /* The connection to get the exclusive locks */ 4883 - u8 writeMask /* Mask of exclusive locks to be acquired */ 4884 -){ 4885 - int rc; /* Result code */ 4886 - unixShm *pX; /* For looping over all sibling connections */ 4887 - 4888 - /* Access to the unixShmFile object is serialized by the caller */ 4889 - assert( sqlite3_mutex_held(pFile->mutex) ); 4890 - 4891 - /* Make sure no sibling connections hold locks that will block this 4892 - ** lock. If any do, return SQLITE_BUSY right away. 4893 - */ 4894 - for(pX=pFile->pFirst; pX; pX=pX->pNext){ 4895 - if( pX==p ) continue; 4896 - if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY; 4897 - if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY; 4898 - } 4899 - 4900 - /* Get the exclusive locks at the system level. Then if successful 4901 - ** also mark the local connection as being locked. 4902 - */ 4903 - rc = unixShmSystemLock(pFile, F_WRLCK, writeMask); 4904 - if( rc==SQLITE_OK ){ 4905 - p->sharedMask &= ~writeMask; 4906 - p->exclMask |= writeMask; 4907 - } 4908 - return rc; 4909 -} 4910 - 4911 -/* 4912 -** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0. 4913 -** 4914 -** This is not a VFS shared-memory method; it is a utility function called 4915 -** by VFS shared-memory methods. 4916 -*/ 4917 -static void unixShmPurge(void){ 4918 - unixShmFile **pp; 4919 - unixShmFile *p; 4920 - assert( unixMutexHeld() ); 4921 - pp = &unixShmFileList; 4922 - while( (p = *pp)!=0 ){ 4923 - if( p->nRef==0 ){ 4924 - if( p->mutex ) sqlite3_mutex_free(p->mutex); 4925 - if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf); 4926 - if( p->h>=0 ) close(p->h); 4927 - *pp = p->pNext; 4928 - sqlite3_free(p); 4929 - }else{ 4930 - pp = &p->pNext; 4931 - } 4932 - } 4933 -} 4934 - 4935 -/* 4936 -** Open a shared-memory area. This particular implementation uses 4937 -** mmapped files. 4938 -** 4939 -** zName is a filename used to identify the shared-memory area. The 4940 -** implementation does not (and perhaps should not) use this name 4941 -** directly, but rather use it as a template for finding an appropriate 4942 -** name for the shared-memory storage. In this implementation, the 4943 -** string "-index" is appended to zName and used as the name of the 4944 -** mmapped file. 4945 -** 4946 -** When opening a new shared-memory file, if no other instances of that 4947 -** file are currently open, in this process or in other processes, then 4948 -** the file must be truncated to zero length or have its header cleared. 4949 -*/ 4950 -static int unixShmOpen( 4951 - sqlite3_vfs *pVfs, /* The VFS */ 4952 - const char *zName, /* Name of the corresponding database file */ 4953 - sqlite3_shm **pShm /* Write the unixShm object created here */ 4954 -){ 4955 - struct unixShm *p = 0; /* The connection to be opened */ 4956 - struct unixShmFile *pFile = 0; /* The underlying mmapped file */ 4957 - int rc; /* Result code */ 4958 - struct unixFileId fid; /* Unix file identifier */ 4959 - struct unixShmFile *pNew; /* Newly allocated pFile */ 4960 - struct stat sStat; /* Result from stat() an fstat() */ 4961 - int nName; /* Size of zName in bytes */ 4962 - 4963 - /* Allocate space for the new sqlite3_shm object. Also speculatively 4964 - ** allocate space for a new unixShmFile and filename. 4965 - */ 4966 - p = sqlite3_malloc( sizeof(*p) ); 4967 - if( p==0 ) return SQLITE_NOMEM; 4968 - memset(p, 0, sizeof(*p)); 4969 - nName = strlen(zName); 4970 - pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 ); 4971 - if( pNew==0 ){ 4972 - sqlite3_free(p); 4973 - return SQLITE_NOMEM; 4974 - } 4975 - memset(pNew, 0, sizeof(*pNew)); 4976 - pNew->zFilename = (char*)&pNew[1]; 4977 - sqlite3_snprintf(nName+12, pNew->zFilename, "%s-wal-index", zName); 4978 - 4979 - /* Look to see if there is an existing unixShmFile that can be used. 4980 - ** If no matching unixShmFile currently exists, create a new one. 4981 - */ 4982 - unixEnterMutex(); 4983 - rc = stat(pNew->zFilename, &sStat); 4984 - if( rc==0 ){ 4985 - memset(&fid, 0, sizeof(fid)); 4986 - fid.dev = sStat.st_dev; 4987 - fid.ino = sStat.st_ino; 4988 - for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){ 4989 - if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break; 4990 - } 4991 - } 4992 - if( pFile ){ 4993 - sqlite3_free(pNew); 4994 - }else{ 4995 - pFile = pNew; 4996 - pNew = 0; 4997 - pFile->h = -1; 4998 - pFile->pNext = unixShmFileList; 4999 - unixShmFileList = pFile; 5000 - 5001 - pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 5002 - if( pFile->mutex==0 ){ 5003 - rc = SQLITE_NOMEM; 5004 - goto shm_open_err; 5005 - } 5006 - pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); 5007 - if( pFile->mutexBuf==0 ){ 5008 - rc = SQLITE_NOMEM; 5009 - goto shm_open_err; 5010 - } 5011 - 5012 - pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664); 5013 - if( pFile->h<0 ){ 5014 - rc = SQLITE_CANTOPEN_BKPT; 5015 - goto shm_open_err; 5016 - } 5017 - 5018 - rc = fstat(pFile->h, &sStat); 5019 - if( rc ){ 5020 - rc = SQLITE_CANTOPEN_BKPT; 5021 - goto shm_open_err; 5022 - } 5023 - pFile->fid.dev = sStat.st_dev; 5024 - pFile->fid.ino = sStat.st_ino; 5025 - 5026 - /* Check to see if another process is holding the dead-man switch. 5027 - ** If not, truncate the file to zero length. 5028 - */ 5029 - if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){ 5030 - if( ftruncate(pFile->h, 0) ){ 5031 - rc = SQLITE_IOERR; 5032 - } 5033 - } 5034 - if( rc==SQLITE_OK ){ 5035 - rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS); 5036 - } 5037 - if( rc ) goto shm_open_err; 5038 - } 5039 - 5040 - /* Make the new connection a child of the unixShmFile */ 5041 - p->pFile = pFile; 5042 - p->pNext = pFile->pFirst; 5043 -#ifdef SQLITE_DEBUG 5044 - p->id = pFile->nextShmId++; 5045 -#endif 5046 - pFile->pFirst = p; 5047 - pFile->nRef++; 5048 - *pShm = (sqlite3_shm*)p; 5049 - unixLeaveMutex(); 5050 - return SQLITE_OK; 5051 - 5052 - /* Jump here on any error */ 5053 -shm_open_err: 5054 - unixShmPurge(); /* This call frees pFile if required */ 5055 - sqlite3_free(p); 5056 - sqlite3_free(pNew); 5057 - *pShm = 0; 5058 - unixLeaveMutex(); 5059 - return rc; 5060 -} 5061 - 5062 -/* 5063 -** Close a connection to shared-memory. Delete the underlying 5064 -** storage if deleteFlag is true. 5065 -*/ 5066 -static int unixShmClose( 5067 - sqlite3_vfs *pVfs, /* The VFS */ 5068 - sqlite3_shm *pSharedMem, /* The shared-memory to be closed */ 5069 - int deleteFlag /* Delete after closing if true */ 5070 -){ 5071 - unixShm *p; /* The connection to be closed */ 5072 - unixShmFile *pFile; /* The underlying shared-memory file */ 5073 - unixShm **pp; /* For looping over sibling connections */ 5074 - 5075 - UNUSED_PARAMETER(pVfs); 5076 - if( pSharedMem==0 ) return SQLITE_OK; 5077 - p = (struct unixShm*)pSharedMem; 5078 - pFile = p->pFile; 5079 - 5080 - /* Verify that the connection being closed holds no locks */ 5081 - assert( p->exclMask==0 ); 5082 - assert( p->sharedMask==0 ); 5083 - 5084 - /* Remove connection p from the set of connections associated with pFile */ 5085 - sqlite3_mutex_enter(pFile->mutex); 5086 - for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} 5087 - *pp = p->pNext; 5088 - 5089 - /* Free the connection p */ 5090 - sqlite3_free(p); 5091 - sqlite3_mutex_leave(pFile->mutex); 5092 - 5093 - /* If pFile->nRef has reached 0, then close the underlying 5094 - ** shared-memory file, too */ 5095 - unixEnterMutex(); 5096 - assert( pFile->nRef>0 ); 5097 - pFile->nRef--; 5098 - if( pFile->nRef==0 ){ 5099 - if( deleteFlag ) unlink(pFile->zFilename); 5100 - unixShmPurge(); 5101 - } 5102 - unixLeaveMutex(); 5103 - 5104 - return SQLITE_OK; 5105 -} 5106 - 5107 -/* 5108 -** Query and/or changes the size of the underlying storage for 5109 -** a shared-memory segment. The reqSize parameter is the new size 5110 -** of the underlying storage, or -1 to do just a query. The size 5111 -** of the underlying storage (after resizing if resizing occurs) is 5112 -** written into pNewSize. 5113 -** 5114 -** This routine does not (necessarily) change the size of the mapping 5115 -** of the underlying storage into memory. Use xShmGet() to change 5116 -** the mapping size. 5117 -** 5118 -** The reqSize parameter is the minimum size requested. The implementation 5119 -** is free to expand the storage to some larger amount if it chooses. 5120 -*/ 5121 -static int unixShmSize( 5122 - sqlite3_vfs *pVfs, /* The VFS */ 5123 - sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */ 5124 - int reqSize, /* Requested size. -1 for query only */ 5125 - int *pNewSize /* Write new size here */ 5126 -){ 5127 - unixShm *p = (unixShm*)pSharedMem; 5128 - unixShmFile *pFile = p->pFile; 5129 - int rc = SQLITE_OK; 5130 - struct stat sStat; 5131 - 5132 - UNUSED_PARAMETER(pVfs); 5133 - 5134 - if( reqSize>=0 ){ 5135 - reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR; 5136 - reqSize *= SQLITE_UNIX_SHM_INCR; 5137 - rc = ftruncate(pFile->h, reqSize); 5138 - } 5139 - if( fstat(pFile->h, &sStat)==0 ){ 5140 - *pNewSize = (int)sStat.st_size; 5141 - }else{ 5142 - *pNewSize = 0; 5143 - rc = SQLITE_IOERR; 5144 - } 5145 - return rc; 5146 -} 5147 - 5148 - 5149 -/* 5150 -** Map the shared storage into memory. The minimum size of the 5151 -** mapping should be reqMapSize if reqMapSize is positive. If 5152 -** reqMapSize is zero or negative, the implementation can choose 5153 -** whatever mapping size is convenient. 5154 -** 5155 -** *ppBuf is made to point to the memory which is a mapping of the 5156 -** underlying storage. A mutex is acquired to prevent other threads 5157 -** from running while *ppBuf is in use in order to prevent other threads 5158 -** remapping *ppBuf out from under this thread. The unixShmRelease() 5159 -** call will release the mutex. However, if the lock state is CHECKPOINT, 5160 -** the mutex is not acquired because CHECKPOINT will never remap the 5161 -** buffer. RECOVER might remap, though, so CHECKPOINT will acquire 5162 -** the mutex if and when it promotes to RECOVER. 5163 -** 5164 -** RECOVER needs to be atomic. The same mutex that prevents *ppBuf from 5165 -** being remapped also prevents more than one thread from being in 5166 -** RECOVER at a time. But, RECOVER sometimes wants to remap itself. 5167 -** To prevent RECOVER from losing its lock while remapping, the 5168 -** mutex is not released by unixShmRelease() when in RECOVER. 5169 -** 5170 -** *pNewMapSize is set to the size of the mapping. 5171 -** 5172 -** *ppBuf and *pNewMapSize might be NULL and zero if no space has 5173 -** yet been allocated to the underlying storage. 5174 -*/ 5175 -static int unixShmGet( 5176 - sqlite3_vfs *pVfs, /* The VFS */ 5177 - sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */ 5178 - int reqMapSize, /* Requested size of mapping. -1 means don't care */ 5179 - int *pNewMapSize, /* Write new size of mapping here */ 5180 - void **ppBuf /* Write mapping buffer origin here */ 5181 -){ 5182 - unixShm *p = (unixShm*)pSharedMem; 5183 - unixShmFile *pFile = p->pFile; 5184 - int rc = SQLITE_OK; 5185 - 5186 - if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){ 5187 - assert( sqlite3_mutex_notheld(pFile->mutex) ); 5188 - sqlite3_mutex_enter(pFile->mutexBuf); 5189 - p->hasMutexBuf = 1; 5190 - } 5191 - sqlite3_mutex_enter(pFile->mutex); 5192 - if( pFile->szMap==0 || reqMapSize>pFile->szMap ){ 5193 - int actualSize; 5194 - if( unixShmSize(pVfs, pSharedMem, -1, &actualSize)==SQLITE_OK 5195 - && reqMapSize<actualSize 5196 - ){ 5197 - reqMapSize = actualSize; 5198 - } 5199 - if( pFile->pMMapBuf ){ 5200 - munmap(pFile->pMMapBuf, pFile->szMap); 5201 - } 5202 - pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED, 5203 - pFile->h, 0); 5204 - pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0; 5205 - } 5206 - *pNewMapSize = pFile->szMap; 5207 - *ppBuf = pFile->pMMapBuf; 5208 - sqlite3_mutex_leave(pFile->mutex); 5209 - return rc; 5210 -} 5211 - 5212 -/* 5213 -** Release the lock held on the shared memory segment to that other 5214 -** threads are free to resize it if necessary. 5215 -** 5216 -** If the lock is not currently held, this routine is a harmless no-op. 5217 -** 5218 -** If the shared-memory object is in lock state RECOVER, then we do not 5219 -** really want to release the lock, so in that case too, this routine 5220 -** is a no-op. 5221 -*/ 5222 -static int unixShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pSharedMem){ 5223 - unixShm *p = (unixShm*)pSharedMem; 5224 - UNUSED_PARAMETER(pVfs); 5225 - if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){ 5226 - assert( sqlite3_mutex_notheld(p->pFile->mutex) ); 5227 - sqlite3_mutex_leave(p->pFile->mutexBuf); 5228 - p->hasMutexBuf = 0; 5229 - } 5230 - return SQLITE_OK; 5231 -} 5232 - 5233 -/* 5234 -** Symbolic names for LOCK states used for debugging. 5235 -*/ 5236 -#ifdef SQLITE_DEBUG 5237 -static const char *azLkName[] = { 5238 - "UNLOCK", 5239 - "READ", 5240 - "READ_FULL", 5241 - "WRITE", 5242 - "PENDING", 5243 - "CHECKPOINT", 5244 - "RECOVER" 5245 -}; 5246 -#endif 5247 - 5248 - 5249 -/* 5250 -** Change the lock state for a shared-memory segment. 5251 -*/ 5252 -static int unixShmLock( 5253 - sqlite3_vfs *pVfs, /* The VFS */ 5254 - sqlite3_shm *pSharedMem, /* Pointer from unixShmOpen() */ 5255 - int desiredLock, /* One of SQLITE_SHM_xxxxx locking states */ 5256 - int *pGotLock /* The lock you actually got */ 5257 -){ 5258 - unixShm *p = (unixShm*)pSharedMem; 5259 - unixShmFile *pFile = p->pFile; 5260 - int rc = SQLITE_PROTOCOL; 5261 - 5262 - UNUSED_PARAMETER(pVfs); 5263 - 5264 - /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never 5265 - ** directly requested; they are side effects from requesting 5266 - ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively. 5267 - */ 5268 - assert( desiredLock==SQLITE_SHM_UNLOCK 5269 - || desiredLock==SQLITE_SHM_READ 5270 - || desiredLock==SQLITE_SHM_WRITE 5271 - || desiredLock==SQLITE_SHM_CHECKPOINT 5272 - || desiredLock==SQLITE_SHM_RECOVER ); 5273 - 5274 - /* Return directly if this is just a lock state query, or if 5275 - ** the connection is already in the desired locking state. 5276 - */ 5277 - if( desiredLock==p->lockState 5278 - || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL) 5279 - ){ 5280 - OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n", 5281 - p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState])); 5282 - if( pGotLock ) *pGotLock = p->lockState; 5283 - return SQLITE_OK; 5284 - } 5285 - 5286 - OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n", 5287 - p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock])); 5288 - 5289 - if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){ 5290 - assert( sqlite3_mutex_notheld(pFile->mutex) ); 5291 - sqlite3_mutex_enter(pFile->mutexBuf); 5292 - p->hasMutexBuf = 1; 5293 - } 5294 - sqlite3_mutex_enter(pFile->mutex); 5295 - switch( desiredLock ){ 5296 - case SQLITE_SHM_UNLOCK: { 5297 - assert( p->lockState!=SQLITE_SHM_RECOVER ); 5298 - unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D); 5299 - rc = SQLITE_OK; 5300 - p->lockState = SQLITE_SHM_UNLOCK; 5301 - break; 5302 - } 5303 - case SQLITE_SHM_READ: { 5304 - if( p->lockState==SQLITE_SHM_UNLOCK ){ 5305 - int nAttempt; 5306 - rc = SQLITE_BUSY; 5307 - assert( p->lockState==SQLITE_SHM_UNLOCK ); 5308 - for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){ 5309 - rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B); 5310 - if( rc==SQLITE_BUSY ){ 5311 - rc = unixShmSharedLock(pFile, p, UNIX_SHM_D); 5312 - if( rc==SQLITE_OK ){ 5313 - p->lockState = SQLITE_SHM_READ_FULL; 5314 - } 5315 - }else{ 5316 - unixShmUnlock(pFile, p, UNIX_SHM_B); 5317 - p->lockState = SQLITE_SHM_READ; 5318 - } 5319 - } 5320 - }else{ 5321 - assert( p->lockState==SQLITE_SHM_WRITE 5322 - || p->lockState==SQLITE_SHM_RECOVER ); 5323 - rc = unixShmSharedLock(pFile, p, UNIX_SHM_A); 5324 - unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D); 5325 - p->lockState = SQLITE_SHM_READ; 5326 - } 5327 - break; 5328 - } 5329 - case SQLITE_SHM_WRITE: { 5330 - assert( p->lockState==SQLITE_SHM_READ 5331 - || p->lockState==SQLITE_SHM_READ_FULL ); 5332 - rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D); 5333 - if( rc==SQLITE_OK ){ 5334 - p->lockState = SQLITE_SHM_WRITE; 5335 - } 5336 - break; 5337 - } 5338 - case SQLITE_SHM_CHECKPOINT: { 5339 - assert( p->lockState==SQLITE_SHM_UNLOCK 5340 - || p->lockState==SQLITE_SHM_PENDING 5341 - ); 5342 - if( p->lockState==SQLITE_SHM_UNLOCK ){ 5343 - rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C); 5344 - if( rc==SQLITE_OK ){ 5345 - p->lockState = SQLITE_SHM_PENDING; 5346 - } 5347 - } 5348 - if( p->lockState==SQLITE_SHM_PENDING ){ 5349 - rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A); 5350 - if( rc==SQLITE_OK ){ 5351 - p->lockState = SQLITE_SHM_CHECKPOINT; 5352 - } 5353 - } 5354 - break; 5355 - } 5356 - default: { 5357 - assert( desiredLock==SQLITE_SHM_RECOVER ); 5358 - assert( p->lockState==SQLITE_SHM_READ 5359 - || p->lockState==SQLITE_SHM_READ_FULL 5360 - ); 5361 - assert( sqlite3_mutex_held(pFile->mutexBuf) ); 5362 - rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C); 5363 - if( rc==SQLITE_OK ){ 5364 - p->lockState = SQLITE_SHM_RECOVER; 5365 - } 5366 - break; 5367 - } 5368 - } 5369 - sqlite3_mutex_leave(pFile->mutex); 5370 - OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n", 5371 - p->id, getpid(), azLkName[p->lockState])); 5372 - if( pGotLock ) *pGotLock = p->lockState; 5373 - return rc; 5374 -} 5375 - 5376 -#else 5377 -# define unixShmOpen 0 5378 -# define unixShmSize 0 5379 -# define unixShmGet 0 5380 -# define unixShmRelease 0 5381 -# define unixShmLock 0 5382 -# define unixShmClose 0 5383 -#endif /* #ifndef SQLITE_OMIT_WAL */ 5384 5410 5385 5411 /* 5386 5412 ************************ End of sqlite3_vfs methods *************************** 5387 5413 ******************************************************************************/ 5388 5414 5389 5415 /****************************************************************************** 5390 5416 ************************** Begin Proxy Locking ******************************** ................................................................................ 6596 6622 unixDlError, /* xDlError */ \ 6597 6623 unixDlSym, /* xDlSym */ \ 6598 6624 unixDlClose, /* xDlClose */ \ 6599 6625 unixRandomness, /* xRandomness */ \ 6600 6626 unixSleep, /* xSleep */ \ 6601 6627 unixCurrentTime, /* xCurrentTime */ \ 6602 6628 unixGetLastError, /* xGetLastError */ \ 6603 - unixShmOpen, /* xShmOpen */ \ 6604 - unixShmSize, /* xShmSize */ \ 6605 - unixShmGet, /* xShmGet */ \ 6606 - unixShmRelease, /* xShmRelease */ \ 6607 - unixShmLock, /* xShmLock */ \ 6608 - unixShmClose, /* xShmClose */ \ 6609 6629 0, /* xRename */ \ 6610 6630 unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \ 6611 6631 } 6612 6632 6613 6633 /* 6614 6634 ** All default VFSes for unix are contained in the following array. 6615 6635 **
Changes to src/pager.c.
3073 3073 u8 *pTmp = (u8 *)pPager->pTmpSpace; 3074 3074 3075 3075 disable_simulated_io_errors(); 3076 3076 sqlite3BeginBenignMalloc(); 3077 3077 pPager->errCode = 0; 3078 3078 pPager->exclusiveMode = 0; 3079 3079 #ifndef SQLITE_OMIT_WAL 3080 - sqlite3WalClose(pPager->pWal, pPager->fd, 3080 + sqlite3WalClose(pPager->pWal, 3081 3081 (pPager->noSync ? 0 : pPager->sync_flags), 3082 3082 pPager->pageSize, pTmp 3083 3083 ); 3084 3084 pPager->pWal = 0; 3085 3085 #endif 3086 3086 pager_reset(pPager); 3087 3087 if( MEMDB ){ ................................................................................ 5874 5874 /* 5875 5875 ** This function is called when the user invokes "PRAGMA checkpoint". 5876 5876 */ 5877 5877 int sqlite3PagerCheckpoint(Pager *pPager){ 5878 5878 int rc = SQLITE_OK; 5879 5879 if( pPager->pWal ){ 5880 5880 u8 *zBuf = (u8 *)pPager->pTmpSpace; 5881 - rc = sqlite3WalCheckpoint(pPager->pWal, pPager->fd, 5881 + rc = sqlite3WalCheckpoint(pPager->pWal, 5882 5882 (pPager->noSync ? 0 : pPager->sync_flags), 5883 5883 pPager->pageSize, zBuf, 5884 5884 pPager->xBusyHandler, pPager->pBusyHandlerArg 5885 5885 ); 5886 5886 } 5887 5887 return rc; 5888 5888 } 5889 5889 5890 5890 int sqlite3PagerWalCallback(Pager *pPager){ 5891 5891 return sqlite3WalCallback(pPager->pWal); 5892 5892 } 5893 + 5894 +/* 5895 +** Return true if the underlying VFS for the given pager supports the 5896 +** primitives necessary for write-ahead logging. 5897 +*/ 5898 +int sqlite3PagerWalSupported(Pager *pPager){ 5899 + const sqlite3_io_methods *pMethods = pPager->fd->pMethods; 5900 + return pMethods->iVersion>=2 && pMethods->xShmOpen!=0; 5901 +} 5893 5902 5894 5903 /* 5895 5904 ** Open a connection to the write-ahead log file for pager pPager. If 5896 5905 ** the log connection is already open, this function is a no-op. 5897 5906 ** 5898 5907 ** The caller must be holding a SHARED lock on the database file to call 5899 5908 ** this function. 5900 5909 */ 5901 5910 int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){ 5902 5911 int rc = SQLITE_OK; /* Return code */ 5903 5912 5904 5913 assert( pPager->state>=PAGER_SHARED ); 5905 5914 if( !pPager->pWal ){ 5915 + if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; 5906 5916 5907 5917 /* Open the connection to the log file. If this operation fails, 5908 5918 ** (e.g. due to malloc() failure), unlock the database file and 5909 5919 ** return an error code. 5910 5920 */ 5911 - rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal); 5921 + rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, 5922 + pPager->zFilename, &pPager->pWal); 5912 5923 if( rc==SQLITE_OK ){ 5913 5924 pPager->journalMode = PAGER_JOURNALMODE_WAL; 5914 5925 } 5915 5926 }else{ 5916 5927 *pisOpen = 1; 5917 5928 } 5918 5929 ................................................................................ 5940 5951 if( !pPager->pWal ){ 5941 5952 int logexists = 0; 5942 5953 rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED); 5943 5954 if( rc==SQLITE_OK ){ 5944 5955 rc = pagerHasWAL(pPager, &logexists); 5945 5956 } 5946 5957 if( rc==SQLITE_OK && logexists ){ 5947 - rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal); 5958 + rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, 5959 + pPager->zFilename, &pPager->pWal); 5948 5960 } 5949 5961 } 5950 5962 5951 5963 /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on 5952 5964 ** the database file, the log and log-summary files will be deleted. 5953 5965 */ 5954 5966 if( rc==SQLITE_OK && pPager->pWal ){ 5955 5967 rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_EXCLUSIVE); 5956 5968 if( rc==SQLITE_OK ){ 5957 - rc = sqlite3WalClose(pPager->pWal, pPager->fd, 5958 - (pPager->noSync ? 0 : pPager->sync_flags), 5969 + rc = sqlite3WalClose(pPager->pWal, 5970 + (pPager->noSync ? 0 : pPager->sync_flags), 5959 5971 pPager->pageSize, (u8*)pPager->pTmpSpace 5960 5972 ); 5961 5973 pPager->pWal = 0; 5962 5974 }else{ 5963 5975 /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock 5964 5976 ** that we did get back to SHARED. */ 5965 5977 sqlite3OsUnlock(pPager->fd, SQLITE_LOCK_SHARED);
Changes to src/pager.h.
131 131 int sqlite3PagerCommitPhaseTwo(Pager*); 132 132 int sqlite3PagerRollback(Pager*); 133 133 int sqlite3PagerOpenSavepoint(Pager *pPager, int n); 134 134 int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); 135 135 int sqlite3PagerSharedLock(Pager *pPager); 136 136 137 137 int sqlite3PagerCheckpoint(Pager *pPager); 138 +int sqlite3PagerWalSupported(Pager *pPager); 138 139 int sqlite3PagerWalCallback(Pager *pPager); 139 140 int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); 140 141 int sqlite3PagerCloseWal(Pager *pPager); 141 142 142 143 /* Functions used to query pager state and configuration. */ 143 144 u8 sqlite3PagerIsreadonly(Pager*); 144 145 int sqlite3PagerRefcount(Pager*);
Changes to src/sqlite.h.in.
649 649 int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); 650 650 int (*xLock)(sqlite3_file*, int); 651 651 int (*xUnlock)(sqlite3_file*, int); 652 652 int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); 653 653 int (*xFileControl)(sqlite3_file*, int op, void *pArg); 654 654 int (*xSectorSize)(sqlite3_file*); 655 655 int (*xDeviceCharacteristics)(sqlite3_file*); 656 + /* Methods above are valid for version 1 */ 657 + int (*xShmOpen)(sqlite3_file*); 658 + int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize); 659 + int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void**); 660 + int (*xShmRelease)(sqlite3_file*); 661 + int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock); 662 + int (*xShmClose)(sqlite3_file*, int deleteFlag); 663 + /* Methods above are valid for version 2 */ 656 664 /* Additional methods may be added in future releases */ 657 665 }; 658 666 659 667 /* 660 668 ** CAPI3REF: Standard File Control Opcodes 661 669 ** 662 670 ** These integer constants are opcodes for the xFileControl method ................................................................................ 814 822 ** the actual number of bytes of randomness obtained. 815 823 ** The xSleep() method causes the calling thread to sleep for at 816 824 ** least the number of microseconds given. The xCurrentTime() 817 825 ** method returns a Julian Day Number for the current date and time. 818 826 ** 819 827 */ 820 828 typedef struct sqlite3_vfs sqlite3_vfs; 821 -typedef struct sqlite3_shm sqlite3_shm; 822 829 struct sqlite3_vfs { 823 830 int iVersion; /* Structure version number (currently 2) */ 824 831 int szOsFile; /* Size of subclassed sqlite3_file */ 825 832 int mxPathname; /* Maximum file pathname length */ 826 833 sqlite3_vfs *pNext; /* Next registered VFS */ 827 834 const char *zName; /* Name of this virtual file system */ 828 835 void *pAppData; /* Pointer to application-specific data */ ................................................................................ 839 846 int (*xSleep)(sqlite3_vfs*, int microseconds); 840 847 int (*xCurrentTime)(sqlite3_vfs*, double*); 841 848 int (*xGetLastError)(sqlite3_vfs*, int, char *); 842 849 /* 843 850 ** The methods above are in version 1 of the sqlite_vfs object 844 851 ** definition. Those that follow are added in version 2 or later 845 852 */ 846 - int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**); 847 - int (*xShmSize)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pNewSize); 848 - int (*xShmGet)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pSize, void**); 849 - int (*xShmRelease)(sqlite3_vfs*, sqlite3_shm*); 850 - int (*xShmLock)(sqlite3_vfs*, sqlite3_shm*, int desiredLock, int *gotLock); 851 - int (*xShmClose)(sqlite3_vfs*, sqlite3_shm*, int deleteFlag); 852 853 int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync); 853 854 int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); 854 855 /* 855 856 ** The methods above are in versions 1 and 2 of the sqlite_vfs object. 856 857 ** New fields may be appended in figure versions. The iVersion 857 858 ** value will increment whenever this happens. 858 859 */
Changes to src/test6.c.
515 515 */ 516 516 static int cfSectorSize(sqlite3_file *pFile){ 517 517 return g.iSectorSize; 518 518 } 519 519 static int cfDeviceCharacteristics(sqlite3_file *pFile){ 520 520 return g.iDeviceCharacteristics; 521 521 } 522 + 523 +/* 524 +** Pass-throughs for WAL support. 525 +*/ 526 +static int cfShmOpen(sqlite3_file *pFile){ 527 + return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile); 528 +} 529 +static int cfShmSize(sqlite3_file *pFile, int reqSize, int *pNew){ 530 + return sqlite3OsShmSize(((CrashFile*)pFile)->pRealFile, reqSize, pNew); 531 +} 532 +static int cfShmGet(sqlite3_file *pFile, int reqSize, int *pSize, void **pp){ 533 + return sqlite3OsShmGet(((CrashFile*)pFile)->pRealFile, reqSize, pSize, pp); 534 +} 535 +static int cfShmRelease(sqlite3_file *pFile){ 536 + return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile); 537 +} 538 +static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){ 539 + return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot); 540 +} 541 +static int cfShmClose(sqlite3_file *pFile, int delFlag){ 542 + return sqlite3OsShmClose(((CrashFile*)pFile)->pRealFile, delFlag); 543 +} 544 + 522 545 523 546 static const sqlite3_io_methods CrashFileVtab = { 524 - 1, /* iVersion */ 547 + 2, /* iVersion */ 525 548 cfClose, /* xClose */ 526 549 cfRead, /* xRead */ 527 550 cfWrite, /* xWrite */ 528 551 cfTruncate, /* xTruncate */ 529 552 cfSync, /* xSync */ 530 553 cfFileSize, /* xFileSize */ 531 554 cfLock, /* xLock */ 532 555 cfUnlock, /* xUnlock */ 533 556 cfCheckReservedLock, /* xCheckReservedLock */ 534 557 cfFileControl, /* xFileControl */ 535 558 cfSectorSize, /* xSectorSize */ 536 - cfDeviceCharacteristics /* xDeviceCharacteristics */ 559 + cfDeviceCharacteristics, /* xDeviceCharacteristics */ 560 + cfShmOpen, /* xShmOpen */ 561 + cfShmSize, /* xShmSize */ 562 + cfShmGet, /* xShmGet */ 563 + cfShmRelease, /* xShmRelease */ 564 + cfShmLock, /* xShmLock */ 565 + cfShmClose /* xShmClose */ 537 566 }; 538 567 539 568 /* 540 569 ** Application data for the crash VFS 541 570 */ 542 571 struct crashAppData { 543 572 sqlite3_vfs *pOrig; /* Wrapped vfs structure */ ................................................................................ 653 682 sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 654 683 return pVfs->xSleep(pVfs, nMicro); 655 684 } 656 685 static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){ 657 686 sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 658 687 return pVfs->xCurrentTime(pVfs, pTimeOut); 659 688 } 660 -static int cfShmOpen(sqlite3_vfs *pCfVfs, const char *zName, sqlite3_shm **pp){ 661 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 662 - return pVfs->xShmOpen(pVfs, zName, pp); 663 -} 664 -static int cfShmSize(sqlite3_vfs *pCfVfs, sqlite3_shm *p, 665 - int reqSize, int *pNew){ 666 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 667 - return pVfs->xShmSize(pVfs, p, reqSize, pNew); 668 -} 669 -static int cfShmGet(sqlite3_vfs *pCfVfs, sqlite3_shm *p, 670 - int reqSize, int *pSize, void **pp){ 671 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 672 - return pVfs->xShmGet(pVfs, p, reqSize, pSize, pp); 673 -} 674 -static int cfShmRelease(sqlite3_vfs *pCfVfs, sqlite3_shm *p){ 675 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 676 - return pVfs->xShmRelease(pVfs, p); 677 -} 678 -static int cfShmLock(sqlite3_vfs *pCfVfs, sqlite3_shm *p, 679 - int desiredLock, int *gotLock){ 680 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 681 - return pVfs->xShmLock(pVfs, p, desiredLock, gotLock); 682 -} 683 -static int cfShmClose(sqlite3_vfs *pCfVfs, sqlite3_shm *p, int delFlag){ 684 - sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData; 685 - return pVfs->xShmClose(pVfs, p, delFlag); 686 -} 687 689 688 690 static int processDevSymArgs( 689 691 Tcl_Interp *interp, 690 692 int objc, 691 693 Tcl_Obj *CONST objv[], 692 694 int *piDeviceChar, 693 695 int *piSectorSize ................................................................................ 806 808 cfDlError, /* xDlError */ 807 809 cfDlSym, /* xDlSym */ 808 810 cfDlClose, /* xDlClose */ 809 811 cfRandomness, /* xRandomness */ 810 812 cfSleep, /* xSleep */ 811 813 cfCurrentTime, /* xCurrentTime */ 812 814 0, /* xGetlastError */ 813 - cfShmOpen, /* xShmOpen */ 814 - cfShmSize, /* xShmSize */ 815 - cfShmGet, /* xShmGet */ 816 - cfShmRelease, /* xShmRelease */ 817 - cfShmLock, /* xShmLock */ 818 - cfShmClose, /* xShmClose */ 819 815 0, /* xRename */ 820 816 0, /* xCurrentTimeInt64 */ 821 817 }; 822 818 823 819 if( objc!=2 ){ 824 820 Tcl_WrongNumArgs(interp, 1, objv, "ENABLE"); 825 821 return TCL_ERROR; ................................................................................ 834 830 } 835 831 836 832 if( crashVfs.pAppData==0 ){ 837 833 sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0); 838 834 crashVfs.mxPathname = pOriginalVfs->mxPathname; 839 835 crashVfs.pAppData = (void *)pOriginalVfs; 840 836 crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile; 841 - if( pOriginalVfs->iVersion<2 || pOriginalVfs->xShmOpen==0 ){ 842 - crashVfs.xShmOpen = 0; 843 - }else{ 844 - crashVfs.xShmOpen = cfShmOpen; 845 - } 846 837 sqlite3_vfs_register(&crashVfs, 0); 847 838 }else{ 848 839 crashVfs.pAppData = 0; 849 840 sqlite3_vfs_unregister(&crashVfs); 850 841 } 851 842 852 843 return TCL_OK;
Changes to src/test_devsym.c.
46 46 static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize); 47 47 static int devsymLock(sqlite3_file*, int); 48 48 static int devsymUnlock(sqlite3_file*, int); 49 49 static int devsymCheckReservedLock(sqlite3_file*, int *); 50 50 static int devsymFileControl(sqlite3_file*, int op, void *pArg); 51 51 static int devsymSectorSize(sqlite3_file*); 52 52 static int devsymDeviceCharacteristics(sqlite3_file*); 53 +static int devsymShmOpen(sqlite3_file*); 54 +static int devsymShmSize(sqlite3_file*,int,int*); 55 +static int devsymShmGet(sqlite3_file*,int,int*,void**); 56 +static int devsymShmRelease(sqlite3_file*); 57 +static int devsymShmLock(sqlite3_file*,int,int*); 58 +static int devsymShmClose(sqlite3_file*,int); 53 59 54 60 /* 55 61 ** Method declarations for devsym_vfs. 56 62 */ 57 63 static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); 58 64 static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir); 59 65 static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *); ................................................................................ 64 70 static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); 65 71 static void devsymDlClose(sqlite3_vfs*, void*); 66 72 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 67 73 static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut); 68 74 static int devsymSleep(sqlite3_vfs*, int microseconds); 69 75 static int devsymCurrentTime(sqlite3_vfs*, double*); 70 76 71 -static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **); 72 -static int devsymShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *); 73 -static int devsymShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **); 74 -static int devsymShmRelease(sqlite3_vfs*, sqlite3_shm *); 75 -static int devsymShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *); 76 -static int devsymShmClose(sqlite3_vfs*, sqlite3_shm *, int); 77 - 78 77 static sqlite3_vfs devsym_vfs = { 79 78 2, /* iVersion */ 80 79 sizeof(devsym_file), /* szOsFile */ 81 80 DEVSYM_MAX_PATHNAME, /* mxPathname */ 82 81 0, /* pNext */ 83 82 DEVSYM_VFS_NAME, /* zName */ 84 83 0, /* pAppData */ ................................................................................ 97 96 0, /* xDlSym */ 98 97 0, /* xDlClose */ 99 98 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 100 99 devsymRandomness, /* xRandomness */ 101 100 devsymSleep, /* xSleep */ 102 101 devsymCurrentTime, /* xCurrentTime */ 103 102 0, /* xGetLastError */ 104 - devsymShmOpen, 105 - devsymShmSize, 106 - devsymShmGet, 107 - devsymShmRelease, 108 - devsymShmLock, 109 - devsymShmClose, 110 - 0, 111 - 0, 103 + 0, /* xRename */ 104 + 0 /* xCurrentTimeInt64 */ 112 105 }; 113 106 114 107 static sqlite3_io_methods devsym_io_methods = { 115 - 1, /* iVersion */ 108 + 2, /* iVersion */ 116 109 devsymClose, /* xClose */ 117 110 devsymRead, /* xRead */ 118 111 devsymWrite, /* xWrite */ 119 112 devsymTruncate, /* xTruncate */ 120 113 devsymSync, /* xSync */ 121 114 devsymFileSize, /* xFileSize */ 122 115 devsymLock, /* xLock */ 123 116 devsymUnlock, /* xUnlock */ 124 117 devsymCheckReservedLock, /* xCheckReservedLock */ 125 118 devsymFileControl, /* xFileControl */ 126 119 devsymSectorSize, /* xSectorSize */ 127 - devsymDeviceCharacteristics /* xDeviceCharacteristics */ 120 + devsymDeviceCharacteristics, /* xDeviceCharacteristics */ 121 + devsymShmOpen, /* xShmOpen */ 122 + devsymShmSize, /* xShmSize */ 123 + devsymShmGet, /* xShmGet */ 124 + devsymShmRelease, /* xShmRelease */ 125 + devsymShmLock, /* xShmLock */ 126 + devsymShmClose /* xShmClose */ 128 127 }; 129 128 130 129 struct DevsymGlobal { 131 130 sqlite3_vfs *pVfs; 132 131 int iDeviceChar; 133 132 int iSectorSize; 134 133 }; ................................................................................ 233 232 234 233 /* 235 234 ** Return the device characteristic flags supported by an devsym-file. 236 235 */ 237 236 static int devsymDeviceCharacteristics(sqlite3_file *pFile){ 238 237 return g.iDeviceChar; 239 238 } 239 + 240 +/* 241 +** Shared-memory methods are all pass-thrus. 242 +*/ 243 +static int devsymShmOpen(sqlite3_file *pFile){ 244 + devsym_file *p = (devsym_file *)pFile; 245 + return sqlite3OsShmOpen(p->pReal); 246 +} 247 +static int devsymShmSize(sqlite3_file *pFile, int reqSize, int *pSize){ 248 + devsym_file *p = (devsym_file *)pFile; 249 + return sqlite3OsShmSize(p->pReal, reqSize, pSize); 250 +} 251 +static int devsymShmGet(sqlite3_file *pFile, int reqSz, int *pSize, void **pp){ 252 + devsym_file *p = (devsym_file *)pFile; 253 + return sqlite3OsShmGet(p->pReal, reqSz, pSize, pp); 254 +} 255 +static int devsymShmRelease(sqlite3_file *pFile){ 256 + devsym_file *p = (devsym_file *)pFile; 257 + return sqlite3OsShmRelease(p->pReal); 258 +} 259 +static int devsymShmLock(sqlite3_file *pFile, int desired, int *pGot){ 260 + devsym_file *p = (devsym_file *)pFile; 261 + return sqlite3OsShmLock(p->pReal, desired, pGot); 262 +} 263 +static int devsymShmClose(sqlite3_file *pFile, int delFlag){ 264 + devsym_file *p = (devsym_file *)pFile; 265 + return sqlite3OsShmClose(p->pReal, delFlag); 266 +} 267 + 268 + 240 269 241 270 /* 242 271 ** Open an devsym file handle. 243 272 */ 244 273 static int devsymOpen( 245 274 sqlite3_vfs *pVfs, 246 275 const char *zName, ................................................................................ 346 375 ** Return the current time as a Julian Day number in *pTimeOut. 347 376 */ 348 377 static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 349 378 return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); 350 379 } 351 380 352 381 353 -static int devsymShmOpen( 354 - sqlite3_vfs *pVfs, 355 - const char *zName, 356 - sqlite3_shm **pp 357 -){ 358 - return g.pVfs->xShmOpen(g.pVfs, zName, pp); 359 -} 360 -static int devsymShmSize( 361 - sqlite3_vfs *pVfs, 362 - sqlite3_shm *p, 363 - int reqSize, 364 - int *pNewSize 365 -){ 366 - return g.pVfs->xShmSize(g.pVfs, p, reqSize, pNewSize); 367 -} 368 -static int devsymShmGet( 369 - sqlite3_vfs *pVfs, 370 - sqlite3_shm *p, 371 - int reqMapSize, 372 - int *pMapSize, 373 - void **pp 374 -){ 375 - return g.pVfs->xShmGet(g.pVfs, p, reqMapSize, pMapSize, pp); 376 -} 377 -static int devsymShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *p){ 378 - return g.pVfs->xShmRelease(g.pVfs, p); 379 -} 380 -static int devsymShmLock( 381 - sqlite3_vfs *pVfs, 382 - sqlite3_shm *p, 383 - int desiredLock, 384 - int *gotLock 385 -){ 386 - return g.pVfs->xShmLock(g.pVfs, p, desiredLock, gotLock); 387 -} 388 -static int devsymShmClose(sqlite3_vfs *pVfs, sqlite3_shm *p, int deleteFlag){ 389 - return g.pVfs->xShmClose(g.pVfs, p, deleteFlag); 390 -} 391 - 392 382 /* 393 383 ** This procedure registers the devsym vfs with SQLite. If the argument is 394 384 ** true, the devsym vfs becomes the new default vfs. It is the only publicly 395 385 ** available function in this file. 396 386 */ 397 387 void devsym_register(int iDeviceChar, int iSectorSize){ 398 388 if( g.pVfs==0 ){ 399 389 g.pVfs = sqlite3_vfs_find(0); 400 390 devsym_vfs.szOsFile += g.pVfs->szOsFile; 401 - devsym_vfs.xShmOpen = (g.pVfs->xShmOpen ? devsymShmOpen : 0); 402 - devsym_vfs.xShmSize = (g.pVfs->xShmSize ? devsymShmSize : 0); 403 - devsym_vfs.xShmGet = (g.pVfs->xShmGet ? devsymShmGet : 0); 404 - devsym_vfs.xShmRelease = (g.pVfs->xShmRelease ? devsymShmRelease : 0); 405 - devsym_vfs.xShmLock = (g.pVfs->xShmLock ? devsymShmLock : 0); 406 - devsym_vfs.xShmClose = (g.pVfs->xShmClose ? devsymShmClose : 0); 407 391 sqlite3_vfs_register(&devsym_vfs, 0); 408 392 } 409 393 if( iDeviceChar>=0 ){ 410 394 g.iDeviceChar = iDeviceChar; 411 395 }else{ 412 396 g.iDeviceChar = 0; 413 397 }
Changes to src/test_onefile.c.
195 195 fsDlOpen, /* xDlOpen */ 196 196 fsDlError, /* xDlError */ 197 197 fsDlSym, /* xDlSym */ 198 198 fsDlClose, /* xDlClose */ 199 199 fsRandomness, /* xRandomness */ 200 200 fsSleep, /* xSleep */ 201 201 fsCurrentTime, /* xCurrentTime */ 202 - 0, /* xShmOpen */ 203 - 0, /* xShmSize */ 204 - 0, /* xShmLock */ 205 - 0, /* xShmClose */ 206 - 0, /* xShmDelete */ 207 202 0, /* xRename */ 208 203 0 /* xCurrentTimeInt64 */ 209 204 }, 210 205 0, /* pFileList */ 211 206 0 /* pParent */ 212 207 }; 213 208 ................................................................................ 220 215 fsSync, /* xSync */ 221 216 fsFileSize, /* xFileSize */ 222 217 fsLock, /* xLock */ 223 218 fsUnlock, /* xUnlock */ 224 219 fsCheckReservedLock, /* xCheckReservedLock */ 225 220 fsFileControl, /* xFileControl */ 226 221 fsSectorSize, /* xSectorSize */ 227 - fsDeviceCharacteristics /* xDeviceCharacteristics */ 222 + fsDeviceCharacteristics, /* xDeviceCharacteristics */ 223 + 0, /* xShmOpen */ 224 + 0, /* xShmSize */ 225 + 0, /* xShmLock */ 226 + 0, /* xShmClose */ 227 + 0, /* xShmDelete */ 228 228 }; 229 229 230 230 231 231 static sqlite3_io_methods tmp_io_methods = { 232 232 1, /* iVersion */ 233 233 tmpClose, /* xClose */ 234 234 tmpRead, /* xRead */ ................................................................................ 237 237 tmpSync, /* xSync */ 238 238 tmpFileSize, /* xFileSize */ 239 239 tmpLock, /* xLock */ 240 240 tmpUnlock, /* xUnlock */ 241 241 tmpCheckReservedLock, /* xCheckReservedLock */ 242 242 tmpFileControl, /* xFileControl */ 243 243 tmpSectorSize, /* xSectorSize */ 244 - tmpDeviceCharacteristics /* xDeviceCharacteristics */ 244 + tmpDeviceCharacteristics, /* xDeviceCharacteristics */ 245 + 0, /* xShmOpen */ 246 + 0, /* xShmSize */ 247 + 0, /* xShmLock */ 248 + 0, /* xShmClose */ 249 + 0, /* xShmDelete */ 245 250 }; 246 251 247 252 /* Useful macros used in several places */ 248 253 #define MIN(x,y) ((x)<(y)?(x):(y)) 249 254 #define MAX(x,y) ((x)>(y)?(x):(y)) 250 255 251 256
Changes to src/test_vfs.c.
12 12 ** 13 13 */ 14 14 #if SQLITE_TEST /* This file is used for testing only */ 15 15 16 16 #include "sqlite3.h" 17 17 #include "sqliteInt.h" 18 18 19 -typedef struct tvfs_file tvfs_file; 20 -struct tvfs_file { 21 - sqlite3_file base; 22 - sqlite3_file *pReal; 23 -}; 24 - 25 19 typedef struct Testvfs Testvfs; 26 20 typedef struct TestvfsShm TestvfsShm; 27 21 typedef struct TestvfsBuffer TestvfsBuffer; 22 +typedef struct TestvfsFile TestvfsFile; 23 + 24 +/* 25 +** An open file handle. 26 +*/ 27 +struct TestvfsFile { 28 + sqlite3_file base; /* Base class. Must be first */ 29 + sqlite3_vfs *pVfs; /* The VFS */ 30 + const char *zFilename; /* Filename as passed to xOpen() */ 31 + sqlite3_file *pReal; /* The real, underlying file descriptor */ 32 + Tcl_Obj *pShmId; /* Shared memory id for Tcl callbacks */ 33 + TestvfsBuffer *pShm; /* Shared memory buffer */ 34 +}; 35 + 28 36 29 37 /* 30 38 ** An instance of this structure is allocated for each VFS created. The 31 39 ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite 32 40 ** is set to point to it. 33 41 */ 34 42 struct Testvfs { ................................................................................ 35 43 char *zName; /* Name of this VFS */ 36 44 sqlite3_vfs *pParent; /* The VFS to use for file IO */ 37 45 sqlite3_vfs *pVfs; /* The testvfs registered with SQLite */ 38 46 Tcl_Interp *interp; /* Interpreter to run script in */ 39 47 int nScript; /* Number of elements in array apScript */ 40 48 Tcl_Obj **apScript; /* Script to execute */ 41 49 TestvfsBuffer *pBuffer; /* List of shared buffers */ 50 + int isNoshm; 42 51 }; 43 52 44 53 /* 45 54 ** A shared-memory buffer. 46 55 */ 47 56 struct TestvfsBuffer { 48 57 char *zFile; /* Associated file name */ 49 58 int n; /* Size of allocated buffer in bytes */ 50 59 u8 *a; /* Buffer allocated using ckalloc() */ 51 60 int nRef; /* Number of references to this object */ 52 61 TestvfsBuffer *pNext; /* Next in linked list of all buffers */ 53 62 }; 54 63 55 -/* 56 -** A shared-memory handle returned by tvfsShmOpen(). 57 -*/ 58 -struct TestvfsShm { 59 - Tcl_Obj *id; /* Name of this handle */ 60 - TestvfsBuffer *pBuffer; /* Underlying buffer */ 61 -}; 62 - 63 64 64 65 #define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent) 65 66 66 67 67 68 /* 68 -** Method declarations for tvfs_file. 69 +** Method declarations for TestvfsFile. 69 70 */ 70 71 static int tvfsClose(sqlite3_file*); 71 72 static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); 72 73 static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); 73 74 static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size); 74 75 static int tvfsSync(sqlite3_file*, int flags); 75 76 static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize); ................................................................................ 93 94 static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); 94 95 static void tvfsDlClose(sqlite3_vfs*, void*); 95 96 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 96 97 static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut); 97 98 static int tvfsSleep(sqlite3_vfs*, int microseconds); 98 99 static int tvfsCurrentTime(sqlite3_vfs*, double*); 99 100 100 -static int tvfsShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **); 101 -static int tvfsShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *); 102 -static int tvfsShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **); 103 -static int tvfsShmRelease(sqlite3_vfs*, sqlite3_shm *); 104 -static int tvfsShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *); 105 -static int tvfsShmClose(sqlite3_vfs*, sqlite3_shm *, int); 101 +static int tvfsShmOpen(sqlite3_file*); 102 +static int tvfsShmSize(sqlite3_file*, int , int *); 103 +static int tvfsShmGet(sqlite3_file*, int , int *, void **); 104 +static int tvfsShmRelease(sqlite3_file*); 105 +static int tvfsShmLock(sqlite3_file*, int , int *); 106 +static int tvfsShmClose(sqlite3_file*, int); 106 107 107 108 static sqlite3_io_methods tvfs_io_methods = { 108 - 1, /* iVersion */ 109 + 2, /* iVersion */ 109 110 tvfsClose, /* xClose */ 110 111 tvfsRead, /* xRead */ 111 112 tvfsWrite, /* xWrite */ 112 113 tvfsTruncate, /* xTruncate */ 113 114 tvfsSync, /* xSync */ 114 115 tvfsFileSize, /* xFileSize */ 115 116 tvfsLock, /* xLock */ 116 117 tvfsUnlock, /* xUnlock */ 117 118 tvfsCheckReservedLock, /* xCheckReservedLock */ 118 119 tvfsFileControl, /* xFileControl */ 119 120 tvfsSectorSize, /* xSectorSize */ 120 - tvfsDeviceCharacteristics /* xDeviceCharacteristics */ 121 + tvfsDeviceCharacteristics, /* xDeviceCharacteristics */ 122 + tvfsShmOpen, /* xShmOpen */ 123 + tvfsShmSize, /* xShmSize */ 124 + tvfsShmGet, /* xShmGet */ 125 + tvfsShmRelease, /* xShmRelease */ 126 + tvfsShmLock, /* xShmLock */ 127 + tvfsShmClose /* xShmClose */ 121 128 }; 122 129 123 130 /* 124 131 ** Close an tvfs-file. 125 132 */ 126 133 static int tvfsClose(sqlite3_file *pFile){ 127 - tvfs_file *p = (tvfs_file *)pFile; 134 + TestvfsFile *p = (TestvfsFile *)pFile; 135 + if( p->pShmId ){ 136 + Tcl_DecrRefCount(p->pShmId); 137 + p->pShmId = 0; 138 + } 139 + if( pFile->pMethods ){ 140 + ckfree((char *)pFile->pMethods); 141 + } 128 142 return sqlite3OsClose(p->pReal); 129 143 } 130 144 131 145 /* 132 146 ** Read data from an tvfs-file. 133 147 */ 134 148 static int tvfsRead( 135 149 sqlite3_file *pFile, 136 150 void *zBuf, 137 151 int iAmt, 138 152 sqlite_int64 iOfst 139 153 ){ 140 - tvfs_file *p = (tvfs_file *)pFile; 154 + TestvfsFile *p = (TestvfsFile *)pFile; 141 155 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); 142 156 } 143 157 144 158 /* 145 159 ** Write data to an tvfs-file. 146 160 */ 147 161 static int tvfsWrite( 148 162 sqlite3_file *pFile, 149 163 const void *zBuf, 150 164 int iAmt, 151 165 sqlite_int64 iOfst 152 166 ){ 153 - tvfs_file *p = (tvfs_file *)pFile; 167 + TestvfsFile *p = (TestvfsFile *)pFile; 154 168 return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); 155 169 } 156 170 157 171 /* 158 172 ** Truncate an tvfs-file. 159 173 */ 160 174 static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ 161 - tvfs_file *p = (tvfs_file *)pFile; 175 + TestvfsFile *p = (TestvfsFile *)pFile; 162 176 return sqlite3OsTruncate(p->pReal, size); 163 177 } 164 178 165 179 /* 166 180 ** Sync an tvfs-file. 167 181 */ 168 182 static int tvfsSync(sqlite3_file *pFile, int flags){ 169 - tvfs_file *p = (tvfs_file *)pFile; 183 + TestvfsFile *p = (TestvfsFile *)pFile; 170 184 return sqlite3OsSync(p->pReal, flags); 171 185 } 172 186 173 187 /* 174 188 ** Return the current file-size of an tvfs-file. 175 189 */ 176 190 static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ 177 - tvfs_file *p = (tvfs_file *)pFile; 191 + TestvfsFile *p = (TestvfsFile *)pFile; 178 192 return sqlite3OsFileSize(p->pReal, pSize); 179 193 } 180 194 181 195 /* 182 196 ** Lock an tvfs-file. 183 197 */ 184 198 static int tvfsLock(sqlite3_file *pFile, int eLock){ 185 - tvfs_file *p = (tvfs_file *)pFile; 199 + TestvfsFile *p = (TestvfsFile *)pFile; 186 200 return sqlite3OsLock(p->pReal, eLock); 187 201 } 188 202 189 203 /* 190 204 ** Unlock an tvfs-file. 191 205 */ 192 206 static int tvfsUnlock(sqlite3_file *pFile, int eLock){ 193 - tvfs_file *p = (tvfs_file *)pFile; 207 + TestvfsFile *p = (TestvfsFile *)pFile; 194 208 return sqlite3OsUnlock(p->pReal, eLock); 195 209 } 196 210 197 211 /* 198 212 ** Check if another file-handle holds a RESERVED lock on an tvfs-file. 199 213 */ 200 214 static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){ 201 - tvfs_file *p = (tvfs_file *)pFile; 215 + TestvfsFile *p = (TestvfsFile *)pFile; 202 216 return sqlite3OsCheckReservedLock(p->pReal, pResOut); 203 217 } 204 218 205 219 /* 206 220 ** File control method. For custom operations on an tvfs-file. 207 221 */ 208 222 static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){ 209 - tvfs_file *p = (tvfs_file *)pFile; 223 + TestvfsFile *p = (TestvfsFile *)pFile; 210 224 return sqlite3OsFileControl(p->pReal, op, pArg); 211 225 } 212 226 213 227 /* 214 228 ** Return the sector-size in bytes for an tvfs-file. 215 229 */ 216 230 static int tvfsSectorSize(sqlite3_file *pFile){ 217 - tvfs_file *p = (tvfs_file *)pFile; 231 + TestvfsFile *p = (TestvfsFile *)pFile; 218 232 return sqlite3OsSectorSize(p->pReal); 219 233 } 220 234 221 235 /* 222 236 ** Return the device characteristic flags supported by an tvfs-file. 223 237 */ 224 238 static int tvfsDeviceCharacteristics(sqlite3_file *pFile){ 225 - tvfs_file *p = (tvfs_file *)pFile; 239 + TestvfsFile *p = (TestvfsFile *)pFile; 226 240 return sqlite3OsDeviceCharacteristics(p->pReal); 227 241 } 228 242 229 243 /* 230 244 ** Open an tvfs file handle. 231 245 */ 232 246 static int tvfsOpen( ................................................................................ 233 247 sqlite3_vfs *pVfs, 234 248 const char *zName, 235 249 sqlite3_file *pFile, 236 250 int flags, 237 251 int *pOutFlags 238 252 ){ 239 253 int rc; 240 - tvfs_file *p = (tvfs_file *)pFile; 254 + TestvfsFile *p = (TestvfsFile *)pFile; 255 + p->pShm = 0; 256 + p->pShmId = 0; 257 + p->zFilename = zName; 258 + p->pVfs = pVfs; 241 259 p->pReal = (sqlite3_file *)&p[1]; 242 260 rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, p->pReal, flags, pOutFlags); 243 261 if( p->pReal->pMethods ){ 244 - pFile->pMethods = &tvfs_io_methods; 262 + sqlite3_io_methods *pMethods; 263 + pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods)); 264 + memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods)); 265 + if( ((Testvfs *)pVfs->pAppData)->isNoshm ){ 266 + pMethods->xShmOpen = 0; 267 + pMethods->xShmGet = 0; 268 + pMethods->xShmSize = 0; 269 + pMethods->xShmRelease = 0; 270 + pMethods->xShmClose = 0; 271 + pMethods->xShmLock = 0; 272 + } 273 + pFile->pMethods = pMethods; 245 274 } 275 + 246 276 return rc; 247 277 } 248 278 249 279 /* 250 280 ** Delete the file located at zPath. If the dirSync argument is true, 251 281 ** ensure the file-system modifications are synced to disk before 252 282 ** returning. ................................................................................ 333 363 /* 334 364 ** Return the current time as a Julian Day number in *pTimeOut. 335 365 */ 336 366 static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 337 367 return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); 338 368 } 339 369 340 -static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){ 341 - TestvfsBuffer *pBuffer = pShm->pBuffer; 370 +static void tvfsGrowBuffer(TestvfsFile *pFd, int reqSize, int *pNewSize){ 371 + TestvfsBuffer *pBuffer = pFd->pShm; 342 372 if( reqSize>pBuffer->n ){ 343 373 pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize); 344 374 memset(&pBuffer->a[pBuffer->n], 0x55, reqSize-pBuffer->n); 345 375 pBuffer->n = reqSize; 346 376 } 347 377 *pNewSize = pBuffer->n; 348 378 } ................................................................................ 401 431 } 402 432 } 403 433 404 434 return 0; 405 435 } 406 436 407 437 static int tvfsShmOpen( 408 - sqlite3_vfs *pVfs, 409 - const char *zName, 410 - sqlite3_shm **pp 438 + sqlite3_file *pFileDes 411 439 ){ 412 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 440 + Testvfs *p; 413 441 int rc = SQLITE_OK; /* Return code */ 414 442 Tcl_Obj *pId = 0; /* Id for this connection */ 415 443 TestvfsBuffer *pBuffer; /* Buffer to open connection to */ 416 - TestvfsShm *pShm; /* New shm handle */ 444 + TestvfsFile *pFd; /* The testvfs file structure */ 445 + 446 + pFd = (TestvfsFile*)pFileDes; 447 + p = (Testvfs *)pFd->pVfs->pAppData; 448 + assert( pFd->pShmId==0 && pFd->pShm==0 ); 417 449 418 450 /* Evaluate the Tcl script: 419 451 ** 420 452 ** SCRIPT xShmOpen FILENAME 421 453 ** 422 454 ** If the script returns an SQLite error code other than SQLITE_OK, an 423 455 ** error is returned to the caller. If it returns SQLITE_OK, the new 424 456 ** connection is named "anon". Otherwise, the value returned by the 425 457 ** script is used as the connection name. 426 458 */ 427 - tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(zName, -1), 0, 0); 459 + tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); 428 460 if( tvfsResultCode(p, &rc) ){ 429 461 if( rc!=SQLITE_OK ) return rc; 430 462 pId = Tcl_NewStringObj("anon", -1); 431 463 }else{ 432 464 pId = Tcl_GetObjResult(p->interp); 433 465 } 434 466 Tcl_IncrRefCount(pId); 435 - 436 - /* Allocate the TestvfsShm handle. */ 437 - pShm = (TestvfsShm *)ckalloc(sizeof(TestvfsShm)); 438 - memset(pShm, 0, sizeof(TestvfsShm)); 439 - pShm->id = pId; 467 + pFd->pShmId = pId; 440 468 441 469 /* Search for a TestvfsBuffer. Create a new one if required. */ 442 470 for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){ 443 - if( 0==strcmp(zName, pBuffer->zFile) ) break; 471 + if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break; 444 472 } 445 473 if( !pBuffer ){ 446 - int nByte = sizeof(TestvfsBuffer) + strlen(zName) + 1; 474 + int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1; 447 475 pBuffer = (TestvfsBuffer *)ckalloc(nByte); 448 476 memset(pBuffer, 0, nByte); 449 477 pBuffer->zFile = (char *)&pBuffer[1]; 450 - strcpy(pBuffer->zFile, zName); 478 + strcpy(pBuffer->zFile, pFd->zFilename); 451 479 pBuffer->pNext = p->pBuffer; 452 480 p->pBuffer = pBuffer; 453 481 } 454 482 455 483 /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */ 456 484 pBuffer->nRef++; 457 - pShm->pBuffer = pBuffer; 458 - *pp = (sqlite3_shm *)pShm; 485 + pFd->pShm = pBuffer; 459 486 return SQLITE_OK; 460 487 } 461 488 462 489 static int tvfsShmSize( 463 - sqlite3_vfs *pVfs, 464 - sqlite3_shm *pShmHandle, 490 + sqlite3_file *pFile, 465 491 int reqSize, 466 492 int *pNewSize 467 493 ){ 468 494 int rc = SQLITE_OK; 469 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 470 - TestvfsShm *pShm = (TestvfsShm *)pShmHandle; 495 + TestvfsFile *pFd = (TestvfsFile *)pFile; 496 + Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 471 497 472 498 tvfsExecTcl(p, "xShmSize", 473 - Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 499 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 474 500 ); 475 501 tvfsResultCode(p, &rc); 476 502 if( rc==SQLITE_OK ){ 477 - tvfsGrowBuffer(pShm, reqSize, pNewSize); 503 + tvfsGrowBuffer(pFd, reqSize, pNewSize); 478 504 } 479 505 return rc; 480 506 } 481 507 482 508 static int tvfsShmGet( 483 - sqlite3_vfs *pVfs, 484 - sqlite3_shm *pShmHandle, 509 + sqlite3_file *pFile, 485 510 int reqMapSize, 486 511 int *pMapSize, 487 512 void **pp 488 513 ){ 489 514 int rc = SQLITE_OK; 490 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 491 - TestvfsShm *pShm = (TestvfsShm *)pShmHandle; 515 + TestvfsFile *pFd = (TestvfsFile *)pFile; 516 + Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 492 517 493 518 tvfsExecTcl(p, "xShmGet", 494 - Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 519 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 495 520 ); 496 521 tvfsResultCode(p, &rc); 497 522 if( rc==SQLITE_OK ){ 498 - tvfsGrowBuffer(pShm, reqMapSize, pMapSize); 499 - *pp = pShm->pBuffer->a; 523 + tvfsGrowBuffer(pFd, reqMapSize, pMapSize); 524 + *pp = pFd->pShm->a; 500 525 } 501 526 return rc; 502 527 } 503 528 504 -static int tvfsShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pShmHandle){ 529 +static int tvfsShmRelease(sqlite3_file *pFile){ 505 530 int rc = SQLITE_OK; 506 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 507 - TestvfsShm *pShm = (TestvfsShm *)pShmHandle; 531 + TestvfsFile *pFd = (TestvfsFile *)pFile; 532 + Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 508 533 509 534 tvfsExecTcl(p, "xShmRelease", 510 - Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 535 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 511 536 ); 512 537 tvfsResultCode(p, &rc); 513 538 514 539 return rc; 515 540 } 516 541 517 542 static int tvfsShmLock( 518 - sqlite3_vfs *pVfs, 519 - sqlite3_shm *pShmHandle, 543 + sqlite3_file *pFile, 520 544 int desiredLock, 521 545 int *gotLock 522 546 ){ 523 547 int rc = SQLITE_OK; 524 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 525 - TestvfsShm *pShm = (TestvfsShm *)pShmHandle; 548 + TestvfsFile *pFd = (TestvfsFile *)pFile; 549 + Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 526 550 char *zLock = ""; 527 551 528 552 switch( desiredLock ){ 529 553 case SQLITE_SHM_READ: zLock = "READ"; break; 530 554 case SQLITE_SHM_WRITE: zLock = "WRITE"; break; 531 555 case SQLITE_SHM_CHECKPOINT: zLock = "CHECKPOINT"; break; 532 556 case SQLITE_SHM_RECOVER: zLock = "RECOVER"; break; 533 557 case SQLITE_SHM_PENDING: zLock = "PENDING"; break; 534 558 case SQLITE_SHM_UNLOCK: zLock = "UNLOCK"; break; 535 559 } 536 560 tvfsExecTcl(p, "xShmLock", 537 - Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 561 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 538 562 Tcl_NewStringObj(zLock, -1) 539 563 ); 540 564 tvfsResultCode(p, &rc); 541 565 if( rc==SQLITE_OK ){ 542 566 *gotLock = desiredLock; 543 567 } 544 568 545 569 return rc; 546 570 } 547 571 548 572 static int tvfsShmClose( 549 - sqlite3_vfs *pVfs, 550 - sqlite3_shm *pShmHandle, 573 + sqlite3_file *pFile, 551 574 int deleteFlag 552 575 ){ 553 576 int rc = SQLITE_OK; 554 - Testvfs *p = (Testvfs *)(pVfs->pAppData); 555 - TestvfsShm *pShm = (TestvfsShm *)pShmHandle; 556 - TestvfsBuffer *pBuffer = pShm->pBuffer; 577 + TestvfsFile *pFd = (TestvfsFile *)pFile; 578 + Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData); 579 + TestvfsBuffer *pBuffer = pFd->pShm; 557 580 581 + assert( pFd->pShmId && pFd->pShm ); 558 582 #if 0 559 583 assert( (deleteFlag!=0)==(pBuffer->nRef==1) ); 560 584 #endif 561 585 562 586 tvfsExecTcl(p, "xShmClose", 563 - Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 587 + Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 564 588 ); 565 589 tvfsResultCode(p, &rc); 566 590 567 591 pBuffer->nRef--; 568 592 if( pBuffer->nRef==0 ){ 569 593 TestvfsBuffer **pp; 570 594 for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext)); 571 595 *pp = (*pp)->pNext; 572 596 ckfree((char *)pBuffer->a); 573 597 ckfree((char *)pBuffer); 574 598 } 575 - Tcl_DecrRefCount(pShm->id); 576 - ckfree((char *)pShm); 599 + Tcl_DecrRefCount(pFd->pShmId); 600 + pFd->pShmId = 0; 601 + pFd->pShm = 0; 577 602 578 603 return rc; 579 604 } 580 605 581 606 static int testvfs_obj_cmd( 582 607 ClientData cd, 583 608 Tcl_Interp *interp, ................................................................................ 683 708 */ 684 709 static int testvfs_cmd( 685 710 ClientData cd, 686 711 Tcl_Interp *interp, 687 712 int objc, 688 713 Tcl_Obj *CONST objv[] 689 714 ){ 690 - 691 715 static sqlite3_vfs tvfs_vfs = { 692 716 2, /* iVersion */ 693 - sizeof(tvfs_file), /* szOsFile */ 717 + sizeof(TestvfsFile), /* szOsFile */ 694 718 0, /* mxPathname */ 695 719 0, /* pNext */ 696 720 0, /* zName */ 697 721 0, /* pAppData */ 698 722 tvfsOpen, /* xOpen */ 699 723 tvfsDelete, /* xDelete */ 700 724 tvfsAccess, /* xAccess */ ................................................................................ 710 734 0, /* xDlSym */ 711 735 0, /* xDlClose */ 712 736 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 713 737 tvfsRandomness, /* xRandomness */ 714 738 tvfsSleep, /* xSleep */ 715 739 tvfsCurrentTime, /* xCurrentTime */ 716 740 0, /* xGetLastError */ 717 - tvfsShmOpen, 718 - tvfsShmSize, 719 - tvfsShmGet, 720 - tvfsShmRelease, 721 - tvfsShmLock, 722 - tvfsShmClose, 723 741 0, 724 742 0, 725 743 }; 726 744 727 745 Testvfs *p; /* New object */ 728 746 sqlite3_vfs *pVfs; /* New VFS */ 729 747 char *zVfs; ................................................................................ 766 784 pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); 767 785 memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); 768 786 pVfs->pAppData = (void *)p; 769 787 pVfs->zName = p->zName; 770 788 pVfs->mxPathname = p->pParent->mxPathname; 771 789 pVfs->szOsFile += p->pParent->szOsFile; 772 790 p->pVfs = pVfs; 773 - if( isNoshm ){ 774 - pVfs->xShmOpen = 0; 775 - pVfs->xShmGet = 0; 776 - pVfs->xShmSize = 0; 777 - pVfs->xShmRelease = 0; 778 - pVfs->xShmClose = 0; 779 - pVfs->xShmLock = 0; 780 - } 791 + p->isNoshm = isNoshm; 781 792 782 793 Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del); 783 794 sqlite3_vfs_register(pVfs, 0); 784 795 785 796 return TCL_OK; 786 797 787 798 bad_args:
Changes to src/vdbe.c.
5244 5244 zFilename = sqlite3PagerFilename(pPager); 5245 5245 pVfs = sqlite3PagerVfs(pPager); 5246 5246 5247 5247 /* Do not allow a transition to journal_mode=WAL for a database 5248 5248 ** in temporary storage or if the VFS does not support xShmOpen. 5249 5249 */ 5250 5250 if( eNew==PAGER_JOURNALMODE_WAL 5251 - && (zFilename[0]==0 /* Temp file */ 5252 - || pVfs->iVersion<2 || pVfs->xShmOpen==0) /* No xShmOpen support */ 5251 + && (zFilename[0]==0 /* Temp file */ 5252 + || !sqlite3PagerWalSupported(pPager)) /* No xShmOpen support */ 5253 5253 ){ 5254 5254 eNew = PAGER_JOURNALMODE_QUERY; 5255 5255 } 5256 5256 5257 5257 if( eNew!=PAGER_JOURNALMODE_QUERY ){ 5258 5258 eOld = sqlite3PagerJournalMode(pPager, PAGER_JOURNALMODE_QUERY); 5259 5259 if( (eNew!=eOld)
Changes to src/wal.c.
121 121 122 122 /* 123 123 ** An open write-ahead log file is represented by an instance of the 124 124 ** following object. 125 125 */ 126 126 struct Wal { 127 127 sqlite3_vfs *pVfs; /* The VFS used to create pFd */ 128 - sqlite3_file *pFd; /* File handle for WAL file */ 128 + sqlite3_file *pDbFd; /* File handle for the database file */ 129 + sqlite3_file *pWalFd; /* File handle for WAL file */ 129 130 u32 iCallback; /* Value to pass to log callback (or 0) */ 130 - sqlite3_shm *pWIndex; /* The open wal-index file */ 131 131 int szWIndex; /* Size of the wal-index that is mapped in mem */ 132 132 u32 *pWiData; /* Pointer to wal-index content in memory */ 133 133 u8 lockState; /* SQLITE_SHM_xxxx constant showing lock state */ 134 134 u8 readerType; /* SQLITE_SHM_READ or SQLITE_SHM_READ_FULL */ 135 135 u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */ 136 + u8 isWindexOpen; /* True if ShmOpen() called on pDbFd */ 136 137 WalIndexHdr hdr; /* Wal-index for current snapshot */ 137 - char *zName; /* Name of underlying storage */ 138 + char *zWalName; /* Name of WAL file */ 138 139 }; 139 140 140 141 141 142 /* 142 143 ** This structure is used to implement an iterator that iterates through 143 144 ** all frames in the log in database page order. Where two or more frames 144 145 ** correspond to the same database page, the iterator visits only the ................................................................................ 219 220 */ 220 221 static int walSetLock(Wal *pWal, int desiredStatus){ 221 222 int rc = SQLITE_OK; /* Return code */ 222 223 if( pWal->exclusiveMode || pWal->lockState==desiredStatus ){ 223 224 pWal->lockState = desiredStatus; 224 225 }else{ 225 226 int got = pWal->lockState; 226 - rc = pWal->pVfs->xShmLock(pWal->pVfs, pWal->pWIndex, desiredStatus, &got); 227 + rc = sqlite3OsShmLock(pWal->pDbFd, desiredStatus, &got); 227 228 pWal->lockState = got; 228 229 if( got==SQLITE_SHM_READ_FULL || got==SQLITE_SHM_READ ){ 229 230 pWal->readerType = got; 230 231 pWal->lockState = SQLITE_SHM_READ; 231 232 } 232 233 } 233 234 return rc; ................................................................................ 400 401 401 402 /* 402 403 ** Release our reference to the wal-index memory map, if we are holding 403 404 ** it. 404 405 */ 405 406 static void walIndexUnmap(Wal *pWal){ 406 407 if( pWal->pWiData ){ 407 - pWal->pVfs->xShmRelease(pWal->pVfs, pWal->pWIndex); 408 + sqlite3OsShmRelease(pWal->pDbFd); 408 409 pWal->pWiData = 0; 409 410 } 410 411 } 411 412 412 413 /* 413 414 ** Map the wal-index file into memory if it isn't already. 414 415 ** 415 416 ** The reqSize parameter is the minimum required size of the mapping. 416 417 ** A value of -1 means "don't care". 417 418 */ 418 419 static int walIndexMap(Wal *pWal, int reqSize){ 419 420 int rc = SQLITE_OK; 420 421 if( pWal->pWiData==0 || reqSize>pWal->szWIndex ){ 421 - rc = pWal->pVfs->xShmGet(pWal->pVfs, pWal->pWIndex, reqSize, 422 - &pWal->szWIndex, (void**)(char*)&pWal->pWiData); 422 + rc = sqlite3OsShmGet(pWal->pDbFd, reqSize, &pWal->szWIndex, 423 + (void**)(char*)&pWal->pWiData); 423 424 if( rc==SQLITE_OK && pWal->pWiData==0 ){ 424 425 /* Make sure pWal->pWiData is not NULL while we are holding the 425 426 ** lock on the mapping. */ 426 427 assert( pWal->szWIndex==0 ); 427 428 pWal->pWiData = &pWal->iCallback; 428 429 } 429 430 if( rc!=SQLITE_OK ){ ................................................................................ 439 440 ** 440 441 ** If enlargeTo is non-negative, then increase the size of the underlying 441 442 ** storage to be at least as big as enlargeTo before remapping. 442 443 */ 443 444 static int walIndexRemap(Wal *pWal, int enlargeTo){ 444 445 int rc; 445 446 int sz; 446 - rc = pWal->pVfs->xShmSize(pWal->pVfs, pWal->pWIndex, enlargeTo, &sz); 447 + rc = sqlite3OsShmSize(pWal->pDbFd, enlargeTo, &sz); 447 448 if( rc==SQLITE_OK && sz>pWal->szWIndex ){ 448 449 walIndexUnmap(pWal); 449 450 rc = walIndexMap(pWal, sz); 450 451 } 451 452 return rc; 452 453 } 453 454 ................................................................................ 557 558 int rc; /* Return Code */ 558 559 i64 nSize; /* Size of log file */ 559 560 WalIndexHdr hdr; /* Recovered wal-index header */ 560 561 561 562 assert( pWal->lockState>SQLITE_SHM_READ ); 562 563 memset(&hdr, 0, sizeof(hdr)); 563 564 564 - rc = sqlite3OsFileSize(pWal->pFd, &nSize); 565 + rc = sqlite3OsFileSize(pWal->pWalFd, &nSize); 565 566 if( rc!=SQLITE_OK ){ 566 567 return rc; 567 568 } 568 569 569 570 if( nSize>WAL_FRAME_HDRSIZE ){ 570 571 u8 aBuf[WAL_FRAME_HDRSIZE]; /* Buffer to load first frame header into */ 571 572 u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ ................................................................................ 575 576 i64 iOffset; /* Next offset to read from log file */ 576 577 int nPgsz; /* Page size according to the log */ 577 578 u32 aCksum[2]; /* Running checksum */ 578 579 579 580 /* Read in the first frame header in the file (to determine the 580 581 ** database page size). 581 582 */ 582 - rc = sqlite3OsRead(pWal->pFd, aBuf, WAL_HDRSIZE, 0); 583 + rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0); 583 584 if( rc!=SQLITE_OK ){ 584 585 return rc; 585 586 } 586 587 587 588 /* If the database page size is not a power of two, or is greater than 588 589 ** SQLITE_MAX_PAGE_SIZE, conclude that the log file contains no valid data. 589 590 */ ................................................................................ 606 607 iFrame = 0; 607 608 for(iOffset=WAL_HDRSIZE; (iOffset+nFrame)<=nSize; iOffset+=nFrame){ 608 609 u32 pgno; /* Database page number for frame */ 609 610 u32 nTruncate; /* dbsize field from frame header */ 610 611 int isValid; /* True if this frame is valid */ 611 612 612 613 /* Read and decode the next log frame. */ 613 - rc = sqlite3OsRead(pWal->pFd, aFrame, nFrame, iOffset); 614 + rc = sqlite3OsRead(pWal->pWalFd, aFrame, nFrame, iOffset); 614 615 if( rc!=SQLITE_OK ) break; 615 616 isValid = walDecodeFrame(aCksum, &pgno, &nTruncate, nPgsz, aData, aFrame); 616 617 if( !isValid ) break; 617 618 rc = walIndexAppend(pWal, ++iFrame, pgno); 618 619 if( rc!=SQLITE_OK ) break; 619 620 620 621 /* If nTruncate is non-zero, this is a commit record. */ ................................................................................ 644 645 return rc; 645 646 } 646 647 647 648 /* 648 649 ** Close an open wal-index. 649 650 */ 650 651 static void walIndexClose(Wal *pWal, int isDelete){ 651 - sqlite3_shm *pWIndex = pWal->pWIndex; 652 - if( pWIndex ){ 653 - sqlite3_vfs *pVfs = pWal->pVfs; 652 + if( pWal->isWindexOpen ){ 654 653 int notUsed; 655 - pVfs->xShmLock(pVfs, pWIndex, SQLITE_SHM_UNLOCK, ¬Used); 656 - pVfs->xShmClose(pVfs, pWIndex, isDelete); 654 + sqlite3OsShmLock(pWal->pDbFd, SQLITE_SHM_UNLOCK, ¬Used); 655 + sqlite3OsShmClose(pWal->pDbFd, isDelete); 656 + pWal->isWindexOpen = 0; 657 657 } 658 658 } 659 659 660 660 /* 661 661 ** Open a connection to the log file associated with database zDb. The 662 662 ** database file does not actually have to exist. zDb is used only to 663 663 ** figure out the name of the log file to open. If the log file does not ................................................................................ 671 671 ** 672 672 ** If the log file is successfully opened, SQLITE_OK is returned and 673 673 ** *ppWal is set to point to a new WAL handle. If an error occurs, 674 674 ** an SQLite error code is returned and *ppWal is left unmodified. 675 675 */ 676 676 int sqlite3WalOpen( 677 677 sqlite3_vfs *pVfs, /* vfs module to open wal and wal-index */ 678 - const char *zDb, /* Name of database file */ 678 + sqlite3_file *pDbFd, /* The open database file */ 679 + const char *zDbName, /* Name of the database file */ 679 680 Wal **ppWal /* OUT: Allocated Wal handle */ 680 681 ){ 681 682 int rc; /* Return Code */ 682 683 Wal *pRet; /* Object to allocate and return */ 683 684 int flags; /* Flags passed to OsOpen() */ 684 - char *zWal; /* Path to WAL file */ 685 + char *zWal; /* Name of write-ahead log file */ 685 686 int nWal; /* Length of zWal in bytes */ 686 687 687 - assert( zDb ); 688 - if( pVfs->xShmOpen==0 ) return SQLITE_CANTOPEN_BKPT; 688 + assert( zDbName && zDbName[0] ); 689 + assert( pDbFd ); 689 690 690 691 /* Allocate an instance of struct Wal to return. */ 691 692 *ppWal = 0; 692 - nWal = strlen(zDb); 693 - pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+5); 693 + nWal = sqlite3Strlen30(zDbName) + 5; 694 + pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal); 694 695 if( !pRet ){ 695 696 return SQLITE_NOMEM; 696 697 } 697 698 698 699 pRet->pVfs = pVfs; 699 - pRet->pFd = (sqlite3_file *)&pRet[1]; 700 - pRet->zName = zWal = pVfs->szOsFile + (char*)pRet->pFd; 701 - sqlite3_snprintf(nWal+5, zWal, "%s-wal", zDb); 702 - rc = pVfs->xShmOpen(pVfs, zDb, &pRet->pWIndex); 700 + pRet->pWalFd = (sqlite3_file *)&pRet[1]; 701 + pRet->pDbFd = pDbFd; 702 + pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd; 703 + sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName); 704 + rc = sqlite3OsShmOpen(pDbFd); 703 705 704 706 /* Open file handle on the write-ahead log file. */ 705 707 if( rc==SQLITE_OK ){ 708 + pRet->isWindexOpen = 1; 706 709 flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL); 707 - rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags); 710 + rc = sqlite3OsOpen(pVfs, zWal, pRet->pWalFd, flags, &flags); 708 711 } 709 712 710 713 if( rc!=SQLITE_OK ){ 711 714 walIndexClose(pRet, 0); 712 - sqlite3OsClose(pRet->pFd); 715 + sqlite3OsClose(pRet->pWalFd); 713 716 sqlite3_free(pRet); 714 717 }else{ 715 718 *ppWal = pRet; 716 719 } 717 720 return rc; 718 721 } 719 722 ................................................................................ 805 808 } 806 809 807 810 /* 808 811 ** Checkpoint the contents of the log file. 809 812 */ 810 813 static int walCheckpoint( 811 814 Wal *pWal, /* Wal connection */ 812 - sqlite3_file *pFd, /* File descriptor open on db file */ 813 815 int sync_flags, /* Flags for OsSync() (or 0) */ 814 816 int nBuf, /* Size of zBuf in bytes */ 815 817 u8 *zBuf /* Temporary buffer to use */ 816 818 ){ 817 819 int rc; /* Return code */ 818 820 int pgsz = pWal->hdr.pgsz; /* Database page-size */ 819 821 WalIterator *pIter = 0; /* Wal iterator context */ ................................................................................ 829 831 if( pWal->hdr.pgsz!=nBuf ){ 830 832 rc = SQLITE_CORRUPT_BKPT; 831 833 goto out; 832 834 } 833 835 834 836 /* Sync the log file to disk */ 835 837 if( sync_flags ){ 836 - rc = sqlite3OsSync(pWal->pFd, sync_flags); 838 + rc = sqlite3OsSync(pWal->pWalFd, sync_flags); 837 839 if( rc!=SQLITE_OK ) goto out; 838 840 } 839 841 840 842 /* Iterate through the contents of the log, copying data to the db file. */ 841 843 while( 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ 842 - rc = sqlite3OsRead(pWal->pFd, zBuf, pgsz, 844 + rc = sqlite3OsRead(pWal->pWalFd, zBuf, pgsz, 843 845 walFrameOffset(iFrame, pgsz) + WAL_FRAME_HDRSIZE 844 846 ); 845 847 if( rc!=SQLITE_OK ) goto out; 846 - rc = sqlite3OsWrite(pFd, zBuf, pgsz, (iDbpage-1)*pgsz); 848 + rc = sqlite3OsWrite(pWal->pDbFd, zBuf, pgsz, (iDbpage-1)*pgsz); 847 849 if( rc!=SQLITE_OK ) goto out; 848 850 } 849 851 850 852 /* Truncate the database file */ 851 - rc = sqlite3OsTruncate(pFd, ((i64)pWal->hdr.nPage*(i64)pgsz)); 853 + rc = sqlite3OsTruncate(pWal->pDbFd, ((i64)pWal->hdr.nPage*(i64)pgsz)); 852 854 if( rc!=SQLITE_OK ) goto out; 853 855 854 856 /* Sync the database file. If successful, update the wal-index. */ 855 857 if( sync_flags ){ 856 - rc = sqlite3OsSync(pFd, sync_flags); 858 + rc = sqlite3OsSync(pWal->pDbFd, sync_flags); 857 859 if( rc!=SQLITE_OK ) goto out; 858 860 } 859 861 pWal->hdr.iLastPg = 0; 860 862 pWal->hdr.iCheck1 = 2; 861 863 pWal->hdr.iCheck2 = 3; 862 864 walIndexWriteHdr(pWal, &pWal->hdr); 863 865 ................................................................................ 872 874 ** 873 875 ** The easiest thing to do would be to write and sync a dummy header 874 876 ** into the log at this point. Unfortunately, that turns out to be 875 877 ** an unwelcome performance hit. Alternatives are... 876 878 */ 877 879 #if 0 878 880 memset(zBuf, 0, WAL_FRAME_HDRSIZE); 879 - rc = sqlite3OsWrite(pWal->pFd, zBuf, WAL_FRAME_HDRSIZE, 0); 881 + rc = sqlite3OsWrite(pWal->pWalFd, zBuf, WAL_FRAME_HDRSIZE, 0); 880 882 if( rc!=SQLITE_OK ) goto out; 881 - rc = sqlite3OsSync(pWal->pFd, pWal->sync_flags); 883 + rc = sqlite3OsSync(pWal->pWalFd, pWal->sync_flags); 882 884 #endif 883 885 884 886 out: 885 887 walIteratorFree(pIter); 886 888 return rc; 887 889 } 888 890 889 891 /* 890 892 ** Close a connection to a log file. 891 893 */ 892 894 int sqlite3WalClose( 893 895 Wal *pWal, /* Wal to close */ 894 - sqlite3_file *pFd, /* Database file */ 895 896 int sync_flags, /* Flags to pass to OsSync() (or 0) */ 896 897 int nBuf, 897 898 u8 *zBuf /* Buffer of at least nBuf bytes */ 898 899 ){ 899 900 int rc = SQLITE_OK; 900 901 if( pWal ){ 901 902 int isDelete = 0; /* True to unlink wal and wal-index files */ ................................................................................ 904 905 ** ordinary, rollback-mode locking methods, this guarantees that the 905 906 ** connection associated with this log file is the only connection to 906 907 ** the database. In this case checkpoint the database and unlink both 907 908 ** the wal and wal-index files. 908 909 ** 909 910 ** The EXCLUSIVE lock is not released before returning. 910 911 */ 911 - rc = sqlite3OsLock(pFd, SQLITE_LOCK_EXCLUSIVE); 912 + rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE); 912 913 if( rc==SQLITE_OK ){ 913 - rc = sqlite3WalCheckpoint(pWal, pFd, sync_flags, nBuf, zBuf, 0, 0); 914 + rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf, 0, 0); 914 915 if( rc==SQLITE_OK ){ 915 916 isDelete = 1; 916 917 } 917 918 walIndexUnmap(pWal); 918 919 } 919 920 920 921 walIndexClose(pWal, isDelete); 921 - sqlite3OsClose(pWal->pFd); 922 + sqlite3OsClose(pWal->pWalFd); 922 923 if( isDelete ){ 923 - sqlite3OsDelete(pWal->pVfs, pWal->zName, 0); 924 + sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0); 924 925 } 925 926 sqlite3_free(pWal); 926 927 } 927 928 return rc; 928 929 } 929 930 930 931 /* ................................................................................ 1187 1188 /* If iRead is non-zero, then it is the log frame number that contains the 1188 1189 ** required page. Read and return data from the log file. 1189 1190 */ 1190 1191 walIndexUnmap(pWal); 1191 1192 if( iRead ){ 1192 1193 i64 iOffset = walFrameOffset(iRead, pWal->hdr.pgsz) + WAL_FRAME_HDRSIZE; 1193 1194 *pInWal = 1; 1194 - return sqlite3OsRead(pWal->pFd, pOut, nOut, iOffset); 1195 + return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset); 1195 1196 } 1196 1197 1197 1198 *pInWal = 0; 1198 1199 return SQLITE_OK; 1199 1200 } 1200 1201 1201 1202 ................................................................................ 1286 1287 int rc = SQLITE_OK; 1287 1288 u8 aCksum[8]; 1288 1289 assert( pWal->lockState==SQLITE_SHM_WRITE ); 1289 1290 1290 1291 pWal->hdr.iLastPg = iFrame; 1291 1292 if( iFrame>0 ){ 1292 1293 i64 iOffset = walFrameOffset(iFrame, pWal->hdr.pgsz) + sizeof(u32)*2; 1293 - rc = sqlite3OsRead(pWal->pFd, aCksum, sizeof(aCksum), iOffset); 1294 + rc = sqlite3OsRead(pWal->pWalFd, aCksum, sizeof(aCksum), iOffset); 1294 1295 pWal->hdr.iCheck1 = sqlite3Get4byte(&aCksum[0]); 1295 1296 pWal->hdr.iCheck2 = sqlite3Get4byte(&aCksum[4]); 1296 1297 } 1297 1298 1298 1299 return rc; 1299 1300 } 1300 1301 ................................................................................ 1330 1331 assert( WAL_FRAME_HDRSIZE>=WAL_HDRSIZE ); 1331 1332 iFrame = pWal->hdr.iLastPg; 1332 1333 if( iFrame==0 ){ 1333 1334 sqlite3Put4byte(aFrame, nPgsz); 1334 1335 sqlite3_randomness(8, &aFrame[4]); 1335 1336 pWal->hdr.iCheck1 = sqlite3Get4byte(&aFrame[4]); 1336 1337 pWal->hdr.iCheck2 = sqlite3Get4byte(&aFrame[8]); 1337 - rc = sqlite3OsWrite(pWal->pFd, aFrame, WAL_HDRSIZE, 0); 1338 + rc = sqlite3OsWrite(pWal->pWalFd, aFrame, WAL_HDRSIZE, 0); 1338 1339 if( rc!=SQLITE_OK ){ 1339 1340 return rc; 1340 1341 } 1341 1342 } 1342 1343 1343 1344 aCksum[0] = pWal->hdr.iCheck1; 1344 1345 aCksum[1] = pWal->hdr.iCheck2; ................................................................................ 1349 1350 i64 iOffset; /* Write offset in log file */ 1350 1351 1351 1352 iOffset = walFrameOffset(++iFrame, nPgsz); 1352 1353 1353 1354 /* Populate and write the frame header */ 1354 1355 nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0; 1355 1356 walEncodeFrame(aCksum, p->pgno, nDbsize, nPgsz, p->pData, aFrame); 1356 - rc = sqlite3OsWrite(pWal->pFd, aFrame, sizeof(aFrame), iOffset); 1357 + rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset); 1357 1358 if( rc!=SQLITE_OK ){ 1358 1359 return rc; 1359 1360 } 1360 1361 1361 1362 /* Write the page data */ 1362 - rc = sqlite3OsWrite(pWal->pFd, p->pData, nPgsz, iOffset + sizeof(aFrame)); 1363 + rc = sqlite3OsWrite(pWal->pWalFd, p->pData, nPgsz, iOffset + sizeof(aFrame)); 1363 1364 if( rc!=SQLITE_OK ){ 1364 1365 return rc; 1365 1366 } 1366 1367 pLast = p; 1367 1368 } 1368 1369 1369 1370 /* Sync the log file if the 'isSync' flag was specified. */ 1370 1371 if( sync_flags ){ 1371 - i64 iSegment = sqlite3OsSectorSize(pWal->pFd); 1372 + i64 iSegment = sqlite3OsSectorSize(pWal->pWalFd); 1372 1373 i64 iOffset = walFrameOffset(iFrame+1, nPgsz); 1373 1374 1374 1375 assert( isCommit ); 1375 1376 1376 1377 if( iSegment<SQLITE_DEFAULT_SECTOR_SIZE ){ 1377 1378 iSegment = SQLITE_DEFAULT_SECTOR_SIZE; 1378 1379 } 1379 1380 iSegment = (((iOffset+iSegment-1)/iSegment) * iSegment); 1380 1381 while( iOffset<iSegment ){ 1381 1382 walEncodeFrame(aCksum,pLast->pgno,nTruncate,nPgsz,pLast->pData,aFrame); 1382 - rc = sqlite3OsWrite(pWal->pFd, aFrame, sizeof(aFrame), iOffset); 1383 + rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset); 1383 1384 if( rc!=SQLITE_OK ){ 1384 1385 return rc; 1385 1386 } 1386 1387 1387 1388 iOffset += WAL_FRAME_HDRSIZE; 1388 - rc = sqlite3OsWrite(pWal->pFd, pLast->pData, nPgsz, iOffset); 1389 + rc = sqlite3OsWrite(pWal->pWalFd, pLast->pData, nPgsz, iOffset); 1389 1390 if( rc!=SQLITE_OK ){ 1390 1391 return rc; 1391 1392 } 1392 1393 nLast++; 1393 1394 iOffset += nPgsz; 1394 1395 } 1395 1396 1396 - rc = sqlite3OsSync(pWal->pFd, sync_flags); 1397 + rc = sqlite3OsSync(pWal->pWalFd, sync_flags); 1397 1398 } 1398 1399 assert( pWal->pWiData==0 ); 1399 1400 1400 1401 /* Append data to the log summary. It is not necessary to lock the 1401 1402 ** wal-index to do this as the RESERVED lock held on the db file 1402 1403 ** guarantees that there are no other writers, and no data that may 1403 1404 ** be in use by existing readers is being overwritten. ................................................................................ 1441 1442 ** 1. Acquire a CHECKPOINT lock 1442 1443 ** 2. Copy the contents of the log into the database file. 1443 1444 ** 3. Zero the wal-index header (so new readers will ignore the log). 1444 1445 ** 4. Drop the CHECKPOINT lock. 1445 1446 */ 1446 1447 int sqlite3WalCheckpoint( 1447 1448 Wal *pWal, /* Wal connection */ 1448 - sqlite3_file *pFd, /* File descriptor open on db file */ 1449 1449 int sync_flags, /* Flags to sync db file with (or 0) */ 1450 1450 int nBuf, /* Size of temporary buffer */ 1451 1451 u8 *zBuf, /* Temporary buffer to use */ 1452 1452 int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ 1453 1453 void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ 1454 1454 ){ 1455 1455 int rc; /* Return code */ ................................................................................ 1475 1475 walSetLock(pWal, SQLITE_SHM_UNLOCK); 1476 1476 return rc; 1477 1477 } 1478 1478 1479 1479 /* Copy data from the log to the database file. */ 1480 1480 rc = walIndexReadHdr(pWal, &isChanged); 1481 1481 if( rc==SQLITE_OK ){ 1482 - rc = walCheckpoint(pWal, pFd, sync_flags, nBuf, zBuf); 1482 + rc = walCheckpoint(pWal, sync_flags, nBuf, zBuf); 1483 1483 } 1484 1484 if( isChanged ){ 1485 1485 /* If a new wal-index header was loaded before the checkpoint was 1486 1486 ** performed, then the pager-cache associated with log pWal is now 1487 1487 ** out of date. So zero the cached wal-index header to ensure that 1488 1488 ** next time the pager opens a snapshot on this database it knows that 1489 1489 ** the cache needs to be reset.
Changes to src/wal.h.
37 37 38 38 /* Connection to a write-ahead log (WAL) file. 39 39 ** There is one object of this type for each pager. 40 40 */ 41 41 typedef struct Wal Wal; 42 42 43 43 /* Open and close a connection to a write-ahead log. */ 44 -int sqlite3WalOpen(sqlite3_vfs*, const char *zDb, Wal **ppWal); 45 -int sqlite3WalClose(Wal *pWal, sqlite3_file *pFd, int sync_flags, int, u8 *); 44 +int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**); 45 +int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *); 46 46 47 47 /* Used by readers to open (lock) and close (unlock) a snapshot. A 48 48 ** snapshot is like a read-transaction. It is the state of the database 49 49 ** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and 50 50 ** preserves the current state even if the other threads or processes 51 51 ** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the 52 52 ** transaction and releases the lock. ................................................................................ 77 77 78 78 /* Write a frame or frames to the log. */ 79 79 int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int); 80 80 81 81 /* Copy pages from the log to the database file */ 82 82 int sqlite3WalCheckpoint( 83 83 Wal *pWal, /* Write-ahead log connection */ 84 - sqlite3_file *pFd, /* File descriptor open on db file */ 85 84 int sync_flags, /* Flags to sync db file with (or 0) */ 86 85 int nBuf, /* Size of buffer nBuf */ 87 86 u8 *zBuf, /* Temporary buffer to use */ 88 87 int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ 89 88 void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ 90 89 ); 91 90