Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for lock structure sharing with AFP-style locking |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
62f15c0aeaec5d778addb6edba62411c |
User & Date: | adam 2009-11-09 19:30:44.000 |
Context
2009-12-07
| ||
23:53 | Merge all changes associated with the version 3.6.21 release into the OS-X branch. (check-in: ad08794d72 user: drh tags: apple-osx) | |
2009-11-09
| ||
19:30 | Fix for lock structure sharing with AFP-style locking (check-in: 62f15c0aea user: adam tags: apple-osx) | |
2009-11-05
| ||
18:31 | Fix an undefined variable on non-Mac builds. (check-in: 9552de8fb5 user: drh tags: apple-osx) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
753 754 755 756 757 758 759 760 761 762 763 764 765 766 | ** object keeps a count of the number of unixFile pointing to it. */ struct unixLockInfo { struct unixLockKey lockKey; /* The lookup key */ int cnt; /* Number of SHARED locks held */ int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ int nRef; /* Number of pointers to this structure */ struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ struct unixLockInfo *pPrev; /* .... doubly linked */ }; /* ** An instance of the following structure is allocated for each open ** inode. This structure keeps track of the number of locks on that | > > > | 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | ** object keeps a count of the number of unixFile pointing to it. */ struct unixLockInfo { struct unixLockKey lockKey; /* The lookup key */ int cnt; /* Number of SHARED locks held */ int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ int nRef; /* Number of pointers to this structure */ #if defined(SQLITE_ENABLE_LOCKING_STYLE) unsigned long long sharedByte; /* for AFP simulated shared lock */ #endif struct unixLockInfo *pNext; /* List of all unixLockInfo objects */ struct unixLockInfo *pPrev; /* .... doubly linked */ }; /* ** An instance of the following structure is allocated for each open ** inode. This structure keeps track of the number of locks on that |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | rc = SQLITE_NOMEM; goto exit_findlockinfo; } memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pLock->pNext = lockList; pLock->pPrev = 0; if( lockList ) lockList->pPrev = pLock; lockList = pLock; }else{ pLock->nRef++; } | > > > | 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 | rc = SQLITE_NOMEM; goto exit_findlockinfo; } memcpy(&pLock->lockKey,&lockKey,sizeof(lockKey)); pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; #if defined(SQLITE_ENABLE_LOCKING_STYLE) pLock->sharedByte = 0; #endif pLock->pNext = lockList; pLock->pPrev = 0; if( lockList ) lockList->pPrev = pLock; lockList = pLock; }else{ pLock->nRef++; } |
︙ | ︙ | |||
2439 2440 2441 2442 2443 2444 2445 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { | < | 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 | #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE /* ** The afpLockingContext structure contains all afp lock specific state */ typedef struct afpLockingContext afpLockingContext; struct afpLockingContext { int reserved; const char *dbPath; /* Name of the open file */ }; struct ByteRangeLockPB2 { unsigned long long offset; /* offset to first byte to lock */ |
︙ | ︙ | |||
2674 2675 2676 2677 2678 2679 2680 | assert( pLock->cnt==0 ); assert( pLock->locktype==0 ); mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; /* Now get the read-lock SHARED_LOCK */ /* note that the quality of the randomness doesn't matter that much */ lk = random(); | | | | 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 | assert( pLock->cnt==0 ); assert( pLock->locktype==0 ); mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff; /* Now get the read-lock SHARED_LOCK */ /* note that the quality of the randomness doesn't matter that much */ lk = random(); pLock->sharedByte = (lk & mask)%(SHARED_SIZE - 1); lrc1 = afpSetLock(context->dbPath, pFile, SHARED_FIRST+pLock->sharedByte, 1, 1); if( IS_LOCK_ERROR(lrc1) ){ lrc1Errno = pFile->lastErrno; } /* Drop the temporary PENDING lock */ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); if( IS_LOCK_ERROR(lrc1) ) { |
︙ | ︙ | |||
2722 2723 2724 2725 2726 2727 2728 | if (!failed && locktype == EXCLUSIVE_LOCK) { /* Acquire an EXCLUSIVE lock */ /* Remove the shared lock before trying the range. we'll need to ** reestablish the shared lock if we can't get the afpUnlock */ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + | | | | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 | if (!failed && locktype == EXCLUSIVE_LOCK) { /* Acquire an EXCLUSIVE lock */ /* Remove the shared lock before trying the range. we'll need to ** reestablish the shared lock if we can't get the afpUnlock */ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pLock->sharedByte, 1, 0)) ){ int failed2 = SQLITE_OK; /* now attemmpt to get the exclusive lock range */ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 1); if( failed && (failed2 = afpSetLock(context->dbPath, pFile, SHARED_FIRST + pLock->sharedByte, 1, 1)) ){ /* Can't reestablish the shared lock. Sqlite can't deal, this is ** a critical I/O error */ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 : SQLITE_IOERR_LOCK; goto afp_end_lock; } |
︙ | ︙ | |||
2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 | ** the requested locking level, this routine is a no-op. */ static int afpUnlock(sqlite3_file *id, int locktype) { int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; struct unixLockInfo *pLock; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; #ifdef SQLITE_TEST int h = pFile->h; #endif assert( pFile ); OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); | > | 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 | ** the requested locking level, this routine is a no-op. */ static int afpUnlock(sqlite3_file *id, int locktype) { int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; struct unixLockInfo *pLock; afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; int skipShared = 0; #ifdef SQLITE_TEST int h = pFile->h; #endif assert( pFile ); OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); |
︙ | ︙ | |||
2813 2814 2815 2816 2817 2818 2819 | || pFile->dbUpdate==0 || pFile->transCntrChng==1 ); pFile->inNormalWrite = 0; #endif if( pFile->locktype==EXCLUSIVE_LOCK ){ rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); | | | > > | > | | > | < > > < < | < | 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 | || pFile->dbUpdate==0 || pFile->transCntrChng==1 ); pFile->inNormalWrite = 0; #endif if( pFile->locktype==EXCLUSIVE_LOCK ){ rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0); if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1) ){ /* only re-establish the shared lock if necessary */ int sharedLockByte = SHARED_FIRST+pLock->sharedByte; rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1); } else { skipShared = 1; } } if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){ rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0); } if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK && context->reserved ){ rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0); if( !rc ){ context->reserved = 0; } } if( rc==SQLITE_OK && (locktype==SHARED_LOCK || pLock->cnt>1)){ pLock->locktype = SHARED_LOCK; } } if( rc==SQLITE_OK && locktype==NO_LOCK ){ /* Decrement the shared lock counter. Release the lock using an ** OS call only when all threads in this same process have released ** the lock. */ unsigned long long sharedLockByte = SHARED_FIRST+pLock->sharedByte; pLock->cnt--; if( pLock->cnt==0 ){ SimulateIOErrorBenign(1); SimulateIOError( h=(-1) ) SimulateIOErrorBenign(0); if( !skipShared ){ rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0); } if( !rc ){ pLock->locktype = NO_LOCK; pFile->locktype = NO_LOCK; } } if( rc==SQLITE_OK ){ struct unixOpenCnt *pOpen = pFile->pOpen; pOpen->nLock--; assert( pOpen->nLock>=0 ); if( pOpen->nLock==0 ){ rc = closePendingFds(pFile); } |
︙ | ︙ |